5 ORDER BY
对查询结果排序,打破并列,并控制 NULL 值的位置。
ORDER BY 对结果集排序。如果没有它,行的顺序就是未定义的:PostgreSQL 可以按规划器认为方便的任意顺序返回行,而且每次运行的顺序都可能不同。如果应用关心顺序,就要明确指定。
本章要点
- 用
ORDER BY column排序 ASC(默认)与DESC- 多列排序(打破并列)
- 控制空值的位置(
NULLS FIRST/NULLS LAST) - 按表达式和位置排序
示例
ORDER BY tablename 按升序排序,ASC 是默认方向;DESC 则反过来。当两行的首个排序键相同时,就用第二个排序键打破并列,以此类推。你可以按任意表达式排序,包括未出现在选择列表中的表达式,也可以按输出位置排序(ORDER BY 1, 2);不过,使用列名要好读得多。
空值的处理值得留意:ASC 把空值排在最后,DESC 则排在最前。用 NULLS FIRST 或 NULLS LAST 可以改变这一默认行为。如果应用无论按哪个方向排序,都希望空值放在最后,就应明确写出来;依赖默认行为,日后有人将 ASC 改为 DESC 时就容易出错。
运行示例
运行方式:
常见陷阱
- 文本排序的结果可能出乎意料:文本排序遵循数据库的排序规则(例如
en_US.UTF-8),它可能不区分大小写,也可能对重音字符做特殊处理。要按字节顺序排序,可用ORDER BY col COLLATE "C"。 - 使用
LIMIT时忘记ORDER BY:没有ORDER BY的LIMIT 10返回的 10 行只是某些行,未必是最前或最小的那些。没有确定的顺序,分页就没有意义。 - 首要排序键相同的两行可以按任意顺序出现。将主键作为最后一个排序键来打破并列,就能得到完全确定的结果(
ORDER BY created_at DESC, id DESC)。 - 对大型结果集排序可能代价很高。如果索引顺序与所需顺序一致,PostgreSQL 可以用索引避免排序。
提示
列出最近的活动时,按 created_at DESC, id DESC 排序。当多行拥有相同时间戳时,id 用于打破并列,让分页保持一致。
动手练习
添加第二个排序列:用 ORDER BY schemaname, tablename 把相同模式的行放在一起,再在各模式内排序。然后按 length(tablename) DESC 排序,看看哪个系统目录表的名字最长。
下载
SQL 文件: order-by.sql · 全部示例文件 · 准备工作