领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

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

nixiaole 2025-09-03 06:41:44 知识剖析 7 ℃

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

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


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

  • ORDER BY: 对结果进行排序。
  • LIMIT: 限制返回结果的数量,实现“分页”等功能。

准备工作:更多的数据

为了让排序效果更明显,我们需要一个稍微大一点的数据集。老规矩,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);

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


9.1ORDER BY:给你的结果排排坐

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

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

SELECT column_list
FROM table_name
WHERE condition
ORDER BY column_to_sort_by [ASC | DESC];
  • ASC (Ascending): 升序排列。从小到大,从早到晚。这是默认的排序方式。
  • DESC (Descending): 降序排列。从大到小,从晚到早。

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

SELECT name, years_known FROM friends
ORDER 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 friends
ORDER 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)

9.2 多列排序

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

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

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

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

SELECT name, years_known FROM friends
ORDER 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, 拼音排序和数据库默认的字符集排序可能不一致,但重点是它们之间有了一个确定的顺序!


9.3LIMIT和OFFSET:分页查询的核心

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

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

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

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

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

SELECT name, years_known FROM friends
ORDER BY years_known DESC
LIMIT 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 friends
ORDER BY id ASC  -- 使用一个绝对唯一的键来排序,保证分页稳定
LIMIT 2 OFFSET 2;

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

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

本章小结

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

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

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

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

Tags:

最近发表
标签列表