跳转到主要内容

5 ORDER BY

对查询结果排序,打破并列,并控制 NULL 值的位置。

ORDER BY 对结果集排序。如果没有它,行的顺序就是未定义的:PostgreSQL 可以按规划器认为方便的任意顺序返回行,而且每次运行的顺序都可能不同。如果应用关心顺序,就要明确指定。

本章要点

  • 用 ORDER BY column 排序
  • ASC(默认)与 DESC
  • 多列排序(打破并列)
  • 控制空值的位置(NULLS FIRST / NULLS LAST)
  • 按表达式和位置排序

示例

示例 5.1 ORDER BY
-- Default ascending
SELECT tablename
FROM pg_tables
WHERE schemaname = 'pg_catalog'
ORDER BY tablename
LIMIT 4;

-- Descending
SELECT tablename
FROM pg_tables
WHERE schemaname = 'pg_catalog'
ORDER BY tablename DESC
LIMIT 4;

-- Multi-column: sort by schema, then by name within schema
SELECT schemaname, tablename
FROM pg_tables
ORDER BY schemaname, tablename
LIMIT 5;

-- NULLs FIRST / LAST: default for ASC is NULLS LAST, for DESC is NULLS FIRST
SELECT * FROM (VALUES (1), (NULL), (2)) AS t(n) ORDER BY n NULLS FIRST;

-- Sort by an expression
SELECT tablename, length(tablename) AS len
FROM pg_tables
WHERE schemaname = 'pg_catalog'
ORDER BY length(tablename) DESC
LIMIT 3;

ORDER BY tablename 按升序排序,ASC 是默认方向;DESC 则反过来。当两行的首个排序键相同时,就用第二个排序键打破并列,以此类推。你可以按任意表达式排序,包括未出现在选择列表中的表达式,也可以按输出位置排序(ORDER BY 1, 2);不过,使用列名要好读得多。

空值的处理值得留意:ASC 把空值排在最后,DESC 则排在最前。用 NULLS FIRST 或 NULLS LAST 可以改变这一默认行为。如果应用无论按哪个方向排序,都希望空值放在最后,就应明确写出来;依赖默认行为,日后有人将 ASC 改为 DESC 时就容易出错。

运行示例

运行方式:

$ psql -f source/order-by.sql postgres
 tablename
--------------
 pg_aggregate
 pg_am
 pg_amop
 pg_amproc
(4 rows)

   tablename
-----------------
 pg_user_mapping
 pg_type
 pg_ts_template
 pg_ts_parser
(4 rows)
 ...

常见陷阱

  • 文本排序的结果可能出乎意料:文本排序遵循数据库的排序规则(例如 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 · 全部示例文件 · 准备工作