第 9 章:排序与限制 (ORDER BY, LIMIT) 📊 - PostgreSQL入门

B站影视 电影资讯 2025-08-04 22:35 1

摘要:现在,我们的查询能力还差最后一点“仪式感”。目前我们 SELECT 出来的数据,顺序都是数据库说了算,有点杂乱无章。如果我们想让结果按照我们指定的规则排列,比如“按年龄从小到大”或者“按认识时间从长到短”,该怎么办呢?

恭喜你,已经完全掌握了数据的增、删、改、查(CRUD)四大金刚!

现在,我们的查询能力还差最后一点“仪式感”。目前我们 SELECT 出来的数据,顺序都是数据库说了算,有点杂乱无章。如果我们想让结果按照我们指定的规则排列,比如“按年龄从小到大”或者“按认识时间从长到短”,该怎么办呢?

这一章,我们就来学习两个让查询结果变得井然有序的强大武器:

为了让排序效果更明显,我们需要一个稍微大一点的数据集。老规矩,TRUNCATE 清空后重新插入:

TRUNCATE TABLE friends;INSERT INTO friends (id, name, birthday, years_known)VALUES (1, '老王', '1990-05-20', 5), (2, '李雷', '1992-08-15', 3), (3, '张三', '1988-01-30', 11), (4, '韩梅梅', '1992-08-15', 3), (5, '赵四', '1978-11-11', 16), (6, '刘能', '1979-03-12', 16);

注意,我们让李雷和韩梅梅的生日与认识年数都相同,赵四和刘能的认识年数也相同,这是为了后面演示多列排序。

ORDER BY 子句允许你根据一列或多列的值,对 SELECT 查询返回的结果集进行排序。

基本语法:
ORDER BY 子句通常放在 SELECT 语句的最后面

SELECT column_listFROM table_nameWHERE conditionORDER BY column_to_sort_by [ASC | DESC];ASC (Ascending): 升序排列。从小到大,从早到晚。这是默认的排序方式。DESC (Descending): 降序排列。从大到小,从晚到早。

示例 1:按认识年数升序排列
找出所有朋友,并按照我们认识他们的年数,从短到长排列。

SELECT name, years_known FROM friendsORDER BY years_known ASC;

因为 ASC 是默认的,所以也可以省略不写:ORDER BY years_known;

结果:

name | years_known+ 李雷 | 3 韩梅梅 | 3 老王 | 5 张三 | 11 赵四 | 16 刘能 | 16(6 rows)

示例 2:按生日降序排列(谁最年轻)
找出所有朋友,并按照他们的生日,从最近到最远排列(也就是从大到小,最年轻的在最前面)。

SELECT name, birthday FROM friendsORDER BY birthday DESC;

结果:

name | birthday+ 李雷 | 1992-08-15 韩梅梅 | 1992-08-15 老王 | 1990-05-20 刘能 | 1979-03-12 赵四 | 1978-11-11 张三 | 1988-01-30(6 rows)

观察上面两个例子,你会发现一个问题:

当按 years_known 排序时,李雷和韩梅梅都是 3 年,他们的前后顺序是不确定的。当按 birthday 排序时,李雷和韩梅梅生日相同,顺序也是不确定的。

如果我们希望在主排序键值相同的情况下,再按第二个、第三个键进行排序,就需要多列排序

示例 3:按认识年数降序,如果年数相同,再按名字升序
我们想看看认识最久的朋友。如果认识时间一样长(比如赵四和刘能),那就按名字的字母顺序排。

SELECT name, years_known FROM friendsORDER BY years_known DESC, name ASC;数据库会首先按照 years_known DESC 来排序。当遇到 years_known 相等的行时,它会在这几行内部,再按照 name ASC 进行二次排序。

结果(注意赵四和刘能的顺序):

name | years_known+ 刘能 | 16 -- 刘(L)在赵(Z)前面 赵四 | 16 张三 | 11 老王 | 5 李雷 | 3 -- 李(L)在韩(H)后面 韩梅梅 | 3(6 rows)

Oops, 拼音排序和数据库默认的字符集排序可能不一致,但重点是它们之间有了一个确定的顺序!

当我们的表里有成千上万条数据时,一次性把它们全都查出来显示给用户,显然是不现实的。这不仅慢,而且用户也看不过来。

这时,我们就需要“分页”——每次只显示一小部分数据。LIMIT 和 OFFSET 就是实现这个功能的神器。

LIMIT [count]: 限制最多返回 count 条记录。OFFSET [count]: 跳过开头的 count 条记录。

LIMIT 和 OFFSET 必须和 ORDER BY 一起使用! 否则,你每次跳过和获取的记录都是不确定的,分页就乱套了。

示例 4:找出我们认识最久的前 3 位朋友

SELECT name, years_known FROM friendsORDER BY years_known DESCLIMIT 3;

结果:

name | years_known+ 赵四 | 16 刘能 | 16 张三 | 11(3 rows)

示例 5:实现分页查询
假设我们每页显示 2 条记录,我们想看第 2 页的数据。

第 1 页: LIMIT 2 OFFSET 0 (跳过0条,取2条)第 2 页: LIMIT 2 OFFSET 2 (跳过2条,取2条)第 3 页: LIMIT 2 OFFSET 4 (跳过4条,取2条)

让我们来获取第 2 页的数据:

SELECT id, name, years_known FROM friendsORDER BY id ASC -- 使用一个绝对唯一的键来排序,保证分页稳定LIMIT 2 OFFSET 2;

结果(ID为 1, 2 的被跳过):

id | name | years_known----+------+ 3 | 张三 | 11 4 | 韩梅梅 | 3(2 rows)

本章小结

太棒了!你已经学会了如何驾驭查询结果的呈现方式。

我们学会了用 ORDER BY 对结果进行升序 (ASC)降序 (DESC) 排列。掌握了多列排序,让排序规则更精细。学会了用 LIMIT 和 OFFSET 来实现获取 Top N 和 分页 这两个极其有用的功能。

至此,SQL 的基础查询部分(第二部分)已经全部完成!你现在拥有的技能,已经足以应对日常 80% 的数据查询和操作任务了。

从下一章开始,我们将进入一个更高级的领域:聚合与分组。我们将学习如何对数据进行统计分析,比如“计算我们朋友的平均年龄”、“统计每年认识了几个朋友”等等。准备好从数据中挖掘更深层次的洞见了吗?我们下一章见!

来源:linux运维菜

相关推荐