第 13.1 节:使用场景

SELECT 语句中的子句有特定的顺序:

SELECT ...
FROM ...
WHERE ...
GROUP BY ...
HAVING ...
ORDER BY ...    -- 放在这里
LIMIT ... OFFSET ...;
(SELECT ...) UNION (SELECT ...) ORDER BY ...   -- 用于对 UNION 的结果排序
SELECT ... GROUP_CONCAT(DISTINCT x ORDER BY ... SEPARATOR ...)
ALTER TABLE ... ORDER BY ...   -- 可能只对 MyISAM 有用;对 InnoDB 无效

第 13.2 节:基本用法

ORDER BY x
  • x 可以是任何数据类型。
  • NULL 值排在非 NULL 值之前。
  • 默认为 ASC(升序,从最低到最高)。
  • 字符串(VARCHAR 等)根据声明的排序规则(COLLATION)排序。
  • ENUM 类型根据其字符串的声明顺序排序。

第 13.3 节:ASC / DESC

ORDER BY x ASC    -- 等同于默认值
ORDER BY x DESC   -- 从最高到最低
ORDER BY lastname, firstname   -- 典型的姓名排序,使用两列
ORDER BY submit_date DESC      -- 最新的在前
ORDER BY submit_date DESC, id ASC  -- 最新的在前,同时完全指定顺序
  • ASC = 升序,DESC = 降序。
  • 即使在 DESC 排序中,NULL 值也排在最前面。
  • 在上述示例中,INDEX(x)、INDEX(lastname, firstname)、INDEX(submit_date) 可以显著提高性能。

但……混合使用 ASC 和 DESC(如最后一个示例)无法利用复合索引来获益。在索引声明中虽然语法上可以写 INDEX(submit_date DESC, id ASC),但 "DESC" 会被忽略。

第 13.4 节:一些技巧

ORDER BY FIND_IN_SET(card_type, "MASTER-CARD, VISA, DISCOVER")   -- 将 'MASTER-CARD' 排在前面
ORDER BY x IS NULL, x   -- 按 'x' 排序,但将 `NULL` 值放在最后

自定义排序

SELECT * FROM some_table
WHERE id IN (118, 17, 113, 23, 72)
ORDER BY FIELD(id, 118, 17, 113, 23, 72);

按指定的 id 顺序返回结果:

id 118 ... id 17 ... id 113 ... id 23 ... id 72 ...

如果 id 本身已经排好序,而你只需要按该顺序检索行,这将非常有用。