目录
[一、SQL 分类(按功能)](#一、SQL 分类(按功能))
[二、SELECT 的执行顺序与典型示例](#二、SELECT 的执行顺序与典型示例)
[1. 执行顺序(逻辑顺序)](#1. 执行顺序(逻辑顺序))
[2. 示例一:销售统计](#2. 示例一:销售统计)
[三、SQLite 表结构:ALTER / 删除列的做法](#三、SQLite 表结构:ALTER / 删除列的做法)
[1. ALTER TABLE 能做什么(SQLite)](#1. ALTER TABLE 能做什么(SQLite))
[2. 在 SQLite 中如何删除一列?](#2. 在 SQLite 中如何删除一列?)
[四、INSERT 细节与 SQLite 特有语法](#四、INSERT 细节与 SQLite 特有语法)
[1. 推荐写法:显式列名](#1. 推荐写法:显式列名)
[2. SQLite:INSERT OR ...](#2. SQLite:INSERT OR ...)
[3. 面试常用说法](#3. 面试常用说法)
[五、DISTINCT 去重规则](#五、DISTINCT 去重规则)
[六、WHERE 条件与基础运算符](#六、WHERE 条件与基础运算符)
[1. WHERE:永远是"按行过滤"](#1. WHERE:永远是“按行过滤”)
[2. NULL 判断要点](#2. NULL 判断要点)
[3. LIKE 模糊匹配](#3. LIKE 模糊匹配)
[七、排序:ORDER BY](#七、排序:ORDER BY)
[八、分页:LIMIT / OFFSET(SQLite / MySQL)](#八、分页:LIMIT / OFFSET(SQLite / MySQL))
[九、聚合函数 & 分组:GROUP BY / HAVING](#九、聚合函数 & 分组:GROUP BY / HAVING)
[1. 聚合函数(对"一组行"算一个值)](#1. 聚合函数(对“一组行”算一个值))
[2. WHERE vs HAVING](#2. WHERE vs HAVING)
[3. 示例:统计每个年龄人数,只保留人数 > 5 的年龄段,并倒序](#3. 示例:统计每个年龄人数,只保留人数 > 5 的年龄段,并倒序)
[1. JOIN 的本质](#1. JOIN 的本质)
[2. INNER JOIN(内连接)](#2. INNER JOIN(内连接))
[3. LEFT JOIN(左外连接)](#3. LEFT JOIN(左外连接))
[4. JOIN vs 子查询(IN / EXISTS)](#4. JOIN vs 子查询(IN / EXISTS))
[1. 视图的本质](#1. 视图的本质)
[2. 视图 vs 表](#2. 视图 vs 表)
[3. 视图的使用场景](#3. 视图的使用场景)
一、SQL 分类(按功能)
口诀:先建表,再改行,再来查,最后保。
-
DDL(Data Definition Language)数据定义语言
-
作用:定义和修改结构(表、视图、索引等)
-
示例:
CREATE、ALTER、DROP -
口诀:定义结构
-
-
DML(Data Manipulation Language)数据操作语言
-
作用:操作行数据(增删改)
-
示例:
INSERT、UPDATE、DELETE -
口诀:操作行
-
-
DQL(Data Query Language)数据查询语言
-
作用:查询数据(结果集)
-
核心:
SELECT -
口诀:查数据
-
-
TCL(Transaction Control Language)事务控制语言
-
作用:控制事务的提交与回滚
-
示例:
BEGIN、COMMIT、ROLLBACK -
口诀:控制成或败
-
二、SELECT 的执行顺序与典型示例
1. 执行顺序(逻辑顺序)
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT
2. 示例一:销售统计
SELECT seller, SUM(amount) AS total
FROM sales
WHERE amount > 0
GROUP BY seller
HAVING SUM(amount) > 1000
ORDER BY total DESC;
理解:
-
FROM sales从
sales表取数据。 -
WHERE amount > 0只保留金额大于 0 的订单。
-
GROUP BY seller按销售人员
seller分组。 -
SUM(amount) AS total统计每个销售的总销售额,命名为
total。 -
HAVING SUM(amount) > 1000只保留总销售额大于 1000 的销售。
-
ORDER BY total DESC按总销售额从大到小排序。
三、SQLite 表结构:ALTER / 删除列的做法
1. ALTER TABLE 能做什么(SQLite)
-
添加列:
ALTER TABLE user ADD COLUMN phone TEXT; -
重命名表:
ALTER TABLE user RENAME TO user_new;
2. 在 SQLite 中如何删除一列?
标准套路:新建新表 + 迁移数据 + 删旧表 + 重命名
步骤:
-
创建不包含该列的新表(结构正确)
-
用
INSERT INTO ... SELECT ...把需要的列迁移过去 -
DROP TABLE删除旧表 -
ALTER TABLE ... RENAME TO ...把新表改回原表名
四、INSERT 细节与 SQLite 特有语法
1. 推荐写法:显式列名
不推荐:
INSERT INTO user
VALUES (1, 'Alice', 20, 'alice@test.com', '2025-01-01 10:00:00');
推荐:
INSERT INTO user (id, name, age, email, created_at)
VALUES (1, 'Alice', 20, 'alice@test.com', '2025-01-01 10:00:00');
2. SQLite:INSERT OR ...
-
OR IGNORE出问题就当没插(不报错,不插入)
INSERT OR IGNORE INTO user (id, name) VALUES (1, 'Alice'); -
OR REPLACE出问题就删旧的,插新的(底层是 delete + insert)
INSERT OR REPLACE INTO user (id, name) VALUES (1, 'Alice');
3. 面试常用说法
-
幂等插入(存在就忽略) :
→
INSERT OR IGNORE -
存在则覆盖 / 不存在则插入 :
→
INSERT OR REPLACE(本质是 delete + insert)
五、DISTINCT 去重规则
-
单列:
SELECT DISTINCT age FROM user;→ 只有
age一列,对age去重。 -
多列:
SELECT DISTINCT name, age FROM user;→ 对
(name, age)这个列组合 去重,→ 只有当
(name, age)都相同时才算重复。
口诀:DISTINCT 作用在 SELECT 后面"所有列的组合"上。
六、WHERE 条件与基础运算符
1. WHERE:永远是"按行过滤"
常见运算符:
-
比较:
=,<>,!=,<,>,<=,>= -
范围:
BETWEEN a AND b(包含 a 和 b) -
集合:
IN (...)/NOT IN (...) -
模糊匹配:
LIKE,NOT LIKE-
%:任意长度 -
_:单个字符
-
-
NULL 判断:
IS NULL/IS NOT NULL
-
逻辑:
AND/OR/NOT- 优先级:
NOT>AND>OR
- 优先级:
2. NULL 判断要点
查 NULL 用
IS,不用=。
-
错误:
age = NULL -
正确:
age IS NULL
3. LIKE 模糊匹配
-
名字以 A 开头:
WHERE name LIKE 'A%'; -
名字中包含 "abc":
WHERE name LIKE '%abc%';
七、排序:ORDER BY
SELECT id, name, age
FROM user
ORDER BY age DESC, id ASC;
要点:
-
ASC:升序(默认) -
DESC:降序 -
支持多列排序:先按前一列排,前一列相等时再看后一列
示例含义:
先按
age降序,如果同龄,再按id升序。
排序只改变结果集顺序 ,不会修改原表数据。
八、分页:LIMIT / OFFSET(SQLite / MySQL)
SELECT *
FROM user
ORDER BY id
LIMIT 10 OFFSET 20;
含义:
跳过前 20 行,取 10 行(第 21~30 行)。
通用分页公式(page 从 1 开始):
LIMIT page_size OFFSET (page - 1) * page_size;
例:第 3 页,每页 20 条:
LIMIT 20 OFFSET (3 - 1) * 20 = 40;
性能注意:OFFSET 越大,扫描的行越多,大分页会慢。
九、聚合函数 & 分组:GROUP BY / HAVING
1. 聚合函数(对"一组行"算一个值)
-
COUNT(*):行数 -
SUM(col):总和 -
AVG(col):平均 -
MIN(col)/MAX(col):最小 / 最大
口诀:聚合函数 = 把一堆行"压扁"成一个统计结果。
2. WHERE vs HAVING
-
WHERE:
-
在
GROUP BY之前 -
对"行"过滤
-
-
HAVING:
-
在
GROUP BY之后 -
对"组"过滤(可用聚合函数)
-
3. 示例:统计每个年龄人数,只保留人数 > 5 的年龄段,并倒序
SELECT age, COUNT(*) AS cnt
FROM user
WHERE age >= 18 -- 在分组前:先把未成年人过滤掉
GROUP BY age -- 按年龄分组
HAVING COUNT(*) > 5 -- 在分组后:只保留人数 > 5 的年龄段
ORDER BY cnt DESC; -- 按人数从多到少排序
理解成一句话:
从
user表里,按
age分组,算每个年龄有多少人(cnt),先过滤掉未成年人,
再只留下人数大于 5 的年龄段,
最后按人数从多到少排序。
十、多表查询:JOIN
1. JOIN 的本质
JOIN = 把多张表"拼在一行里",常用来查详细信息(比如:用户 + 订单)。
表结构示例:
CREATE TABLE user (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE "order" (
id INTEGER PRIMARY KEY,
user_id INTEGER,
amount REAL
);
2. INNER JOIN(内连接)
SELECT u.id, u.name, o.amount
FROM user u
JOIN "order" o ON u.id = o.user_id;
-- 等价于 INNER JOIN
只返回两边都能对上号 的记录。
只包含"有订单的用户"。
3. LEFT JOIN(左外连接)
SELECT u.id, u.name, o.amount
FROM user u
LEFT JOIN "order" o ON u.id = o.user_id;
左边(user)一个都不能少;
如果右边(order)没有匹配,就用
NULL填。
典型需求: 查所有用户及其订单金额,没下单的用户金额为 NULL。
→ 使用 LEFT JOIN。
4. JOIN vs 子查询(IN / EXISTS)
-
JOIN:
-
作用:把多表字段拼到一行
-
场景:查询详细信息(用户 + 订单等)
-
-
子查询 + IN / EXISTS:
-
作用:只用于过滤
-
场景:判断"是否存在 / 是否在某个集合中"
-
例:查出有下过订单的用户:
-
IN 写法:
SELECT * FROM user WHERE id IN (SELECT user_id FROM "order"); -
EXISTS 写法:
SELECT * FROM user u WHERE EXISTS ( SELECT 1 FROM "order" o WHERE o.user_id = u.id );
十一、视图(View)
1. 视图的本质
CREATE VIEW user_order_view AS
SELECT u.id AS user_id,
u.name,
o.id AS order_id,
o.amount
FROM user u
LEFT JOIN "order" o ON u.id = o.user_id;
视图 = 保存好的 SELECT 查询,本身一般不存数据。
使用视图就像查表:
SELECT *
FROM user_order_view
WHERE amount > 100;
2. 视图 vs 表
-
表(Table):
-
真正存数据的结构
-
像 Excel 文件,数据是实打实写进去的
-
-
视图(View):
-
存的是"查询公式"(
SELECT ...定义) -
每次查询视图时,实时去访问底层表
-
像 Excel 里的公式单元格,打开时重新计算
-
口诀:表存"数据",视图存"查询公式"。
3. 视图的使用场景
-
封装复杂查询,方便复用(多表 JOIN、分组统计等)
-
做逻辑隔离:对外只暴露视图,不直接暴露底层表
如果你愿意,下一步我可以帮你把这些内容整理成一份"面试速答版",每个知识点压缩成 1~2 句中文话术 + 1 条典型 SQL,方便你在面试前快速过一遍。