条件查询与排序分页

写给初学者:每个概念都从”为什么需要它”开始讲,配合通俗比喻和完整可运行 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,公式页乘每页量;

翻页必先排好序,否则顺序乱一场。

相关链接