SQL 入门指南:排序与分页查询(ORDER BY 多字段排序、LIMIT 分页实战)
在 SQL 查询中,我们常需要 “按报名时间先后看活动名单”“只看第 2 页的活动报名数据”—— 这些需求靠基础查询无法实现,而ORDER BY(排序) 和LIMIT(分页) 就是解决这类问题的核心工具。今天我们用 “校园活动报名记录表” 为案例,从零学会排序和分页的用法,代码可直接复制运行,看完就能上手。
我整理了超多的学习资料,包含专业、课程、考试等资源,还有游戏和软件合集
学习资料合集文档https://www.kdocs.cn/l/cjchDXwklk1B
一、先搞懂:为什么需要排序与分页?
先想两个场景:
- 学校举办 “校园歌手大赛”,收集到 100 条报名数据,想按 “报名时间从晚到早” 看最新报名的同学,或按 “学院 + 报名时间” 分组排序 —— 这需要ORDER BY;
- 报名数据太多,一页显示 20 条,想查看第 2 页(21-40 条)或第 3 页(41-60 条)的数据,避免一次性加载所有数据卡顿 —— 这需要LIMIT。
核心作用:
- ORDER BY:让查询结果按指定规则排序,避免数据杂乱无章;
- LIMIT:限制查询结果的行数,实现分页加载,提升效率。
准备案例数据:校园活动报名记录表
我们创建全新的 “校园活动报名记录表”(表名:campus_activity_signup),包含报名 ID、学生信息、活动信息、报名时间等字段,代码可直接运行:
-- 创建校园活动报名记录表
CREATE TABLE campus_activity_signup (signup_id INT PRIMARY KEY AUTO_INCREMENT, -- 报名ID(自增,唯一标识)student_id CHAR(10) NOT NULL, -- 学号(如2025001001)student_name VARCHAR(20) NOT NULL, -- 学生姓名college VARCHAR(30) NOT NULL, -- 所属学院(如计算机学院、文学院)activity_name VARCHAR(50) NOT NULL, -- 活动名称(如校园歌手大赛、运动会)signup_time DATETIME NOT NULL, -- 报名时间signup_status VARCHAR(10) NOT NULL -- 报名状态(已确认、待确认、已取消)
);-- 插入15条测试数据(覆盖不同学院、活动、报名时间)
INSERT INTO campus_activity_signup (student_id, student_name, college, activity_name, signup_time, signup_status)
VALUES
('2025001001', '张三', '计算机学院', '校园歌手大赛', '2025-09-01 08:30:00', '已确认'),
('2025002001', '李四', '文学院', '校园歌手大赛', '2025-09-01 09:15:00', '已确认'),
('2025003001', '王五', '商学院', '运动会', '2025-09-01 10:00:00', '待确认'),
('2025001002', '赵六', '计算机学院', '运动会', '2025-09-01 10:20:00', '已确认'),
('2025002002', '孙七', '文学院', '校园歌手大赛', '2025-09-02 08:45:00', '待确认'),
('2025003002', '周八', '商学院', '校园歌手大赛', '2025-09-02 09:30:00', '已确认'),
('2025001003', '吴九', '计算机学院', '运动会', '2025-09-02 11:00:00', '已取消'),
('2025002003', '郑十', '文学院', '运动会', '2025-09-03 09:00:00', '已确认'),
('2025003003', '钱十一', '商学院', '校园歌手大赛', '2025-09-03 10:15:00', '待确认'),
('2025004001', '冯十二', '外国语学院', '校园歌手大赛', '2025-09-03 14:20:00', '已确认'),
('2025004002', '陈十三', '外国语学院', '运动会', '2025-09-04 08:50:00', '待确认'),
('2025001004', '褚十四', '计算机学院', '校园歌手大赛', '2025-09-04 09:40:00', '已确认'),
('2025002004', '卫十五', '文学院', '校园歌手大赛', '2025-09-04 10:30:00', '已取消'),
('2025003004', '蒋十六', '商学院', '运动会', '2025-09-05 09:10:00', '已确认'),
('2025004003', '沈十七', '外国语学院', '运动会', '2025-09-05 11:20:00', '待确认');-- 查看表数据(确认插入成功)
SELECT * FROM campus_activity_signup LIMIT 5;
表中数据如下(简化展示):
signup_id | student_id | student_name | college | activity_name | signup_time | signup_status |
1 | 2025001001 | 张三 | 计算机学院 | 校园歌手大赛 | 2025-09-01 08:30:00 | 已确认 |
2 | 2025002001 | 李四 | 文学院 | 校园歌手大赛 | 2025-09-01 09:15:00 | 已确认 |
3 | 2025003001 | 王五 | 商学院 | 运动会 | 2025-09-01 10:00:00 | 待确认 |
4 | 2025001002 | 赵六 | 计算机学院 | 运动会 | 2025-09-01 10:20:00 | 已确认 |
5 | 2025002002 | 孙七 | 文学院 | 校园歌手大赛 | 2025-09-02 08:45:00 | 待确认 |
二、ORDER BY:实现排序查询
ORDER BY是 SQL 中用于排序的关键字,支持 “单字段排序” 和 “多字段排序”,还能指定 “升序” 或 “降序”。
1. 基础用法:单字段排序(升序 / 降序)
语法:SELECT 字段 FROM 表名 ORDER BY 排序字段 [ASC/DESC];
- ASC:升序(默认,可省略),比如时间从早到晚、数字从小到大;
- DESC:降序,比如时间从晚到早、数字从大到小。
例子 1:按报名时间降序,查看最新报名的同学
需求:查看 “校园歌手大赛” 的报名数据,按 “报名时间从晚到早” 排序,显示学生姓名、学院、报名时间。
代码:
SELECT student_name AS 学生姓名,college AS 所属学院,signup_time AS 报名时间
FROM campus_activity_signup
WHERE activity_name = '校园歌手大赛' -- 只看校园歌手大赛的报名
ORDER BY signup_time DESC; -- 按报名时间降序(最新的在前)
运行结果(前 5 条):
学生姓名 | 所属学院 | 报名时间 |
卫十五 | 文学院 | 2025-09-04 10:30:00 |
褚十四 | 计算机学院 | 2025-09-04 09:40:00 |
冯十二 | 外国语学院 | 2025-09-03 14:20:00 |
钱十一 | 商学院 | 2025-09-03 10:15:00 |
周八 | 商学院 | 2025-09-02 09:30:00 |
可以看到:最新的报名记录(2025-09-04 10:30)排在最前面,符合 “降序” 需求。
例子 2:按报名状态升序,查看不同状态的报名数据
需求:查看 “运动会” 的报名数据,按 “报名状态(已确认→待确认→已取消)” 升序排序,显示学生姓名、状态、报名时间。
代码:
SELECT student_name AS 学生姓名,signup_status AS 报名状态,signup_time AS 报名时间
FROM campus_activity_signup
WHERE activity_name = '运动会'
ORDER BY signup_status ASC; -- 按状态升序(默认按字符顺序排序)
运行结果:
学生姓名 | 报名状态 | 报名时间 |
赵六 | 已确认 | 2025-09-01 10:20:00 |
郑十 | 已确认 | 2025-09-03 09:00:00 |
蒋十六 | 已确认 | 2025-09-05 09:10:00 |
王五 | 待确认 | 2025-09-01 10:00:00 |
陈十三 | 待确认 | 2025-09-04 08:50:00 |
沈十七 | 待确认 | 2025-09-05 11:20:00 |
吴九 | 已取消 | 2025-09-02 11:00:00 |
解释:字符型字段按 “拼音首字母顺序” 排序,“已确认”(Y)在 “待确认”(D)之后?不对,这里实际是按 “ASCII 码顺序” 排序 ——“待” 的 ASCII 码比 “已” 小,所以 “待确认” 会排在 “已确认” 前面?别纠结细节,记住:想按自定义顺序排序(如 “已确认→待确认→已取消”),后续可学FIELD()函数,入门阶段先掌握基础排序逻辑即可。
2. 进阶用法:多字段排序
当 “单字段排序无法区分顺序” 时,需要用 “多字段排序”—— 先按第一个字段排序,第一个字段相同的,再按第二个字段排序。
例子 3:按 “学院 + 报名时间” 排序,查看同一学院的报名顺序
需求:查看所有活动的报名数据,先按 “学院升序”(同一学院的排在一起),同一学院内按 “报名时间降序”(最新报名的在前),显示学院、学生姓名、活动名称、报名时间。
代码:
SELECT college AS 所属学院,student_name AS 学生姓名,activity_name AS 活动名称,signup_time AS 报名时间
FROM campus_activity_signup
-- 多字段排序:先按学院升序,再按报名时间降序
ORDER BY college ASC, signup_time DESC;
运行结果(计算机学院部分):
所属学院 | 学生姓名 | 活动名称 | 报名时间 |
计算机学院 | 褚十四 | 校园歌手大赛 | 2025-09-04 09:40:00 |
计算机学院 | 吴九 | 运动会 | 2025-09-02 11:00:00 |
计算机学院 | 赵六 | 运动会 | 2025-09-01 10:20:00 |
计算机学院 | 张三 | 校园歌手大赛 | 2025-09-01 08:30:00 |
可以看到:所有 “计算机学院” 的学生排在一起,且同一学院内,报名时间晚的(2025-09-04)排在前面,符合 “多字段排序” 的逻辑。
关键规则:ORDER BY后字段的顺序很重要,先按第一个字段排序,第一个字段相同的才会按第二个字段排序,以此类推。
三、LIMIT:实现分页查询
当查询结果有几十、几百条时,一次性显示会很杂乱,用LIMIT可以 “按页显示”,比如每页显示 5 条,查看第 1 页(1-5 条)、第 2 页(6-10 条)等。
1. 基础用法:限制返回行数(LIMIT N)
语法:SELECT 字段 FROM 表名 LIMIT 行数;
作用:只返回查询结果的前 N 行数据。
例子 4:查看 “已确认” 状态的前 3 条报名数据
需求:查看所有 “报名状态为已确认” 的数据,只显示前 3 条,按报名时间降序。
代码:
SELECT student_name AS 学生姓名,activity_name AS 活动名称,signup_time AS 报名时间
FROM campus_activity_signup
WHERE signup_status = '已确认'
ORDER BY signup_time DESC
LIMIT 3; -- 只返回前3条数据
运行结果:
学生姓名 | 活动名称 | 报名时间 |
蒋十六 | 运动会 | 2025-09-05 09:10:00 |
褚十四 | 校园歌手大赛 | 2025-09-04 09:40:00 |
冯十二 | 校园歌手大赛 | 2025-09-03 14:20:00 |
2. 进阶用法:分页查询(LIMIT 偏移量,行数)
语法:SELECT 字段 FROM 表名 LIMIT 偏移量, 每页行数;
- 偏移量:从第几条数据开始(注意:SQL 中数据从 0 开始计数,不是 1);
- 每页行数:每页显示多少条数据。
分页公式(重要):
想查看第 M 页,每页显示 N 条数据:
偏移量 = (M - 1) * N,LIMIT 偏移量, N
比如:
- 第 1 页(1-5 条):M=1,N=5 → 偏移量 = 0 → LIMIT 0, 5;
- 第 2 页(6-10 条):M=2,N=5 → 偏移量 = 5 → LIMIT 5, 5;
- 第 3 页(11-15 条):M=3,N=5 → 偏移量 = 10 → LIMIT 10, 5。
例子 5:分页查看所有报名数据(每页 5 条,查看第 2 页)
需求:查看所有报名数据,按报名时间降序,每页显示 5 条,查看第 2 页(6-10 条)。
代码:
SELECT signup_id AS 报名ID,student_name AS 学生姓名,activity_name AS 活动名称,signup_time AS 报名时间
FROM campus_activity_signup
ORDER BY signup_time DESC
-- 第2页,每页5条:偏移量=(2-1)*5=5,所以LIMIT 5,5
LIMIT 5, 5;
运行结果(第 2 页,6-10 条):
报名 ID | 学生姓名 | 活动名称 | 报名时间 |
12 | 褚十四 | 校园歌手大赛 | 2025-09-04 09:40:00 |
11 | 陈 |