条件查询与排序分页
写给初学者:每个概念都从”为什么需要它”开始讲,配合通俗比喻和完整可运行 SQL。
一、条件筛选(WHERE)
1.1 为什么需要 WHERE?
SELECT * FROM users 返回所有行,但实际需求永远是”查满足某某条件的”。比如:
-
查年龄大于 25 岁的用户
-
查余额在 100 到 500 之间的用户
-
查用户名包含 “user” 的用户
WHERE 就是过滤器——符合条件的留下,不符合的扔掉。
1.2 比较运算符
-- = 等于(注意:SQL 里等于只有一个等号!)
SELECT * FROM users WHERE age = 25;
-- != 或 <> 不等于
SELECT * FROM users WHERE age != 25;
-- > 大于
SELECT * FROM users WHERE balance > 100;
-- < 小于
SELECT * FROM users WHERE age < 25;
-- >= 大于等于
SELECT * FROM users WHERE balance >= 100;
-- <= 小于等于
SELECT * FROM users WHERE age <= 30;
CAUTION
SQL 里判断等于用
=,不是==。 这跟 Python / JavaScript 不一样。
1.3 逻辑运算:AND、OR、NOT
-- AND:两个条件都必须满足
SELECT * FROM users
WHERE age > 20 AND balance > 100;
-- OR:满足任意一个即可
SELECT * FROM users
WHERE age < 20 OR age > 30;
-- NOT:取反
SELECT * FROM users
WHERE NOT age = 25; -- 等价于 age != 25
-- 混合使用(用括号明确优先级!)
SELECT * FROM users
WHERE (age > 25 OR balance > 200) AND email LIKE '%@qq.com';
WARNING
AND 优先级高于 OR!
A OR B AND C等于A OR (B AND C),不是(A OR B) AND C。不确定就用括号,别靠记忆。
1.4 IN —— 多值匹配
-- 不用 IN(写很多个 OR,很啰嗦)
SELECT * FROM users
WHERE age = 20 OR age = 25 OR age = 30;
-- 用 IN(简洁清晰)
SELECT * FROM users
WHERE age IN (20, 25, 30);
-- NOT IN:不在这些值里
SELECT * FROM users
WHERE age NOT IN (20, 25, 30);
1.5 BETWEEN —— 范围查询
-- 查询余额在 100 到 300 之间的用户(包含边界)
SELECT * FROM users
WHERE balance BETWEEN 100 AND 300;
-- 等价于 balance >= 100 AND balance <= 300
-- NOT BETWEEN:不在范围内
SELECT * FROM users
WHERE balance NOT BETWEEN 100 AND 300;
1.6 LIKE —— 模糊匹配
-- % 表示任意多个字符(包括 0 个)
-- _ 表示任意一个字符
-- 查用户名以 "user" 开头的
SELECT * FROM users WHERE username LIKE 'user%';
-- 匹配: user01, user02, user_abc
-- 不匹配: zhangsan, lisi
-- 查用户名包含 "san" 的
SELECT * FROM users WHERE username LIKE '%san%';
-- 匹配: zhangsan
-- 查用户名以 "qq.com" 结尾的
SELECT * FROM users WHERE email LIKE '%@qq.com';
-- 查用户名第 5 个字符是 0 的
SELECT * FROM users WHERE username LIKE '____0%';
-- user0 开头的: user01, user02, ...
常用 LIKE 模式速查:
| 模式 | 含义 | 例子 |
|---|---|---|
LIKE '张%' | 以”张”开头 | 张三、张三丰 |
LIKE '%三' | 以”三”结尾 | 张三、李三 |
LIKE '%三%' | 包含”三” | 张三、李三、三哥 |
LIKE '张_' | ”张”开头,后面恰好 1 个字符 | 张三(不匹配张三丰) |
LIKE '张__' | ”张”开头,后面恰好 2 个字符 | 张三丰(不匹配张三) |
1.7 IS NULL / IS NOT NULL
-- ⚠️ 判断 NULL 不能用 = 或 !=,必须用 IS NULL / IS NOT NULL
-- ✅ 正确:查没有填年龄的用户
SELECT * FROM users WHERE age IS NULL;
-- ✅ 正确:查有填年龄的用户
SELECT * FROM users WHERE age IS NOT NULL;
-- ❌ 错误:这样查不到任何结果!
SELECT * FROM users WHERE age = NULL; -- NULL 不等于任何值,包括 NULL 自己
SELECT * FROM users WHERE age != NULL; -- 同样查不到
为什么
age = NULL无效?
因为 NULL 表示”未知”。一个未知值不能和另一个未知值比较。就像”我不知道的年龄”和”你不知道的年龄”——没法说它们相等。
1.8 WHERE 常见错误
-- ❌ 错误 1:用 = 判断 NULL
SELECT * FROM users WHERE age = NULL;
-- ❌ 错误 2:字符串没加引号
SELECT * FROM users WHERE username = zhangsan; -- 报错
-- ✅ 正确
SELECT * FROM users WHERE username = 'zhangsan';
-- ❌ 错误 3:数字加了引号(不会报错但语义不对,且影响性能)
SELECT * FROM users WHERE age = '25';
-- ✅ 正确
SELECT * FROM users WHERE age = 25;
-- ❌ 错误 4:用 == 判断相等
SELECT * FROM users WHERE age == 25; -- 报错
二、排序(ORDER BY)
2.1 为什么需要排序?
数据库存储是无序的——同一张表,这次查到张三在前面,下次可能跑最后。如果你想”按年龄从小到大排”或”按余额从高到低排”,就必须用 ORDER BY。
2.2 基本用法
-- ASC:升序(从小到大),默认值,可以不写
SELECT * FROM users ORDER BY age ASC;
-- DESC:降序(从大到小)
SELECT * FROM users ORDER BY balance DESC;
-- 不写 ASC/DESC,默认升序
SELECT * FROM users ORDER BY age;
2.3 多字段排序
-- 先按年龄升序,年龄相同的按余额降序
SELECT username, age, balance FROM users
ORDER BY age ASC, balance DESC;
输出:
+----------+------+---------+
| username | age | balance |
+----------+------+---------+
| user01 | 20 | 50.00 |
| user02 | 22 | 100.00 |
| zhangsan | 25 | 100.00 |
| user03 | 25 | 200.00 | -- ← 年龄相同,按余额降序
| wangwu | 28 | 0.00 |
| user04 | 28 | 150.00 |
| lisi | 30 | 0.00 |
| user05 | 30 | 300.00 |
| zhaoliu | NULL | 0.00 | -- ← NULL 默认排在最前面
+----------+------+---------+
2.4 NULL 的排序位置
-- MySQL 默认:ASC 时 NULL 在最前面,DESC 时 NULL 在最后面
-- 用 IS NULL 可以把 NULL 排到最后
SELECT * FROM users
ORDER BY age IS NULL, age ASC;
-- age IS NULL:有年龄的为 0,NULL 的为 1 → 有年龄的排前面
三、分页(LIMIT)
3.1 为什么需要分页?
淘宝搜索”手机”,有 10 万个结果,不可能一次全返回给你。实际做法是:每页显示 20 条,你看第 1 页返回 1-20 条,点”下一页”返回 21-40 条。
这就是分页——LIMIT 控制”返回多少条”,OFFSET 控制”跳过多少条”。
3.2 基本语法
-- LIMIT n:只返回前 n 条
SELECT * FROM users LIMIT 3;
-- 结果:只有 id=1,2,3 的三行
-- LIMIT n OFFSET m:跳过前 m 条,返回 n 条
SELECT * FROM users LIMIT 3 OFFSET 3;
-- 结果:跳过前 3 条,返回 id=4,5,6 的三行
3.3 分页公式
-- 第 1 页(每页 3 条)
SELECT * FROM users LIMIT 3 OFFSET 0; -- 行 1-3
-- 第 2 页(每页 3 条)
SELECT * FROM users LIMIT 3 OFFSET 3; -- 行 4-6
-- 第 3 页(每页 3 条)
SELECT * FROM users LIMIT 3 OFFSET 6; -- 行 7-9
通用公式:
LIMIT 每页条数 OFFSET 每页条数 × (页码 - 1)
例如每页 3 条,第 2 页:LIMIT 3 OFFSET 3 × (2-1) = LIMIT 3 OFFSET 3
3.4 结合 ORDER BY 才有意义
-- ❌ 不排序直接分页——顺序不可控,每次可能不一样
SELECT * FROM users LIMIT 3 OFFSET 0;
-- ✅ 先排序再分页——保证每页数据是确定的
SELECT * FROM users ORDER BY id ASC LIMIT 3 OFFSET 0;
WARNING
分页必须配合 ORDER BY,否则顺序是乱的。 这是生产环境最容易出的 Bug 之一。
速查表
| 操作 | 语法 | 一句话解释 |
|---|---|---|
| 等于 | WHERE 列 = 值 | 精确匹配 |
| 不等于 | WHERE 列 != 值 | 排除某个值 |
| 比较 | > < >= <= | 大小比较 |
| 逻辑与 | 条件1 AND 条件2 | 两个都必须满足 |
| 逻辑或 | 条件1 OR 条件2 | 满足一个即可 |
| 逻辑非 | NOT 条件 | 取反 |
| 多值匹配 | WHERE 列 IN (a, b, c) | 等于 a、b、c 中的任意一个 |
| 范围 | WHERE 列 BETWEEN a AND b | 在 a 和 b 之间(含边界) |
| 模糊搜索 | WHERE 列 LIKE '%关键字%' | 模糊匹配,% 是通配符 |
| 判空 | WHERE 列 IS NULL | 找没有填的 |
| 升序 | ORDER BY 列 ASC | 从小到大(默认) |
| 降序 | ORDER BY 列 DESC | 从大到小 |
| 多字段排序 | ORDER BY 列1 ASC, 列2 DESC | 先按列1排,相同再按列2排 |
| 分页 | LIMIT n OFFSET m | 跳过 m 条,取 n 条 |
| 取前 n 条 | LIMIT n | 只返回前 n 条 |
速记卡(面试闪卡)
Q1:一句话讲清「条件查询与排序分页」到底是什么?
A:WHERE 过滤行、ORDER BY 排序、LIMIT 分页,是 SQL 取出想要数据的三板斧。
Q2:一、条件筛选(WHERE) —— 怎么理解?
A:像筛豆子:WHERE 就是滤网,符合条件的留下。= 相等、> < 比较,AND/OR/NOT 组合,IN 多值,BETWEEN 范围,LIKE ‘%张%’ 模糊,IS NULL 判空(NULL 不能用 = 比)。注意 SQL 等于用单等号 =,不是 ==。
Q3:二、排序(ORDER BY) —— 怎么理解?
A:像排队:ORDER BY age ASC 从小到大、DESC 从大到小;多字段先按第一列排、相同再排第二列。MySQL 里 ASC 时 NULL 排最前。ORDER BY(排序子句)让无序存储变有序输出。
Q4:三、分页(LIMIT) —— 怎么理解?
A:像翻书:LIMIT n 取前 n 条,LIMIT n OFFSET m 跳过 m 条取 n 条。第 p 页公式 LIMIT 每页 OFFSET 每页×(p-1)。OFFSET(偏移量)决定从哪页开始,LIMIT(限制条数)控制每页多少。
Q5:四、分页必须配合排序(实战要点) —— 怎么理解?
A:像取号排队必须先定顺序:不排序直接分页,数据库返回顺序不可控,每次可能不一样(生产大坑)。所以 LIMIT 前一定先 ORDER BY 某个稳定字段(如 id),保证每页数据确定。这是面试常考的易错点。
Q6:核心速记主线有哪些?
-
WHERE 过滤行:比较 / 逻辑 / IN / BETWEEN / LIKE / IS NULL
-
ORDER BY 排序:ASC 默认升序、DESC 降序、支持多字段
-
LIMIT 分页:LIMIT n OFFSET m,第 p 页 = 每页×(p-1)
-
分页必须配合 ORDER BY,否则顺序乱套
口诀
A:条件筛选 WHERE 网,比较逻辑 IN 范围亮;
排序 ORDER BY 定,ASC 升序 DESC 降;
分页 LIMIT 配 OFFSET,公式页乘每页量;
翻页必先排好序,否则顺序乱一场。
相关链接
-
目录:00-MySQL
-
上一篇:02-CRUD操作与数据类型
-
下一篇:04-子查询与多表连接JOIN