mysql 5.7及更早版本中null默认升序排最前、降序排最后,需用order by col is null, col(null靠后)或order by col is null desc, col(null靠前)显式控制,该写法兼容所有mysql版本且安全可靠。

MySQL 5.7 及更早版本:用 IS NULL 布尔表达式控制顺序
MySQL 不支持 NULLS FIRST/NULLS LAST,但 col IS NULL 返回布尔值(0 或 1),可直接用于排序。升序时 FALSE(即 0)在前,TRUE(即 1)在后。
让非空值优先升序、NULL 垫底:
ORDER BY col IS NULL, col
让 NULL 排最前、非空值降序:
ORDER BY col IS NULL DESC, col DESC
-
col IS NULL DESC把TRUE(1)排前面,FALSE(0)排后面 - 第二级
col DESC只作用于非NULL行,不影响NULL分组 - 该写法兼容所有 MySQL 版本,且不依赖类型假设,比
COALESCE更安全
PostgreSQL / Oracle / MySQL 8.0+:用 NULLS LAST 直接声明意图
这些数据库支持标准 SQL 的 NULLS LAST,但语法位置很关键:必须紧跟在列名和方向之后,不能独立成项。
正确写法(升序 + NULL 垫底):
ORDER BY col ASC NULLS LAST
错误写法(会被解析为两列排序):
ORDER BY col ASC, NULLS LAST ← 报错:unknown column "NULLS"
-
ASC NULLS LAST和DESC NULLS FIRST是等价逻辑,但前者更贴近「非空优先」的业务表述 - MySQL 8.0+ 支持此语法,但旧版应用升级后需检查 SQL 是否混用了不兼容写法
- PostgreSQL 中若字段是字符串,
NULLS LAST仍会按字典序排非空值,无需额外处理
避免用 COALESCE() 或 IFNULL() 替换 NULL 排序
看似简洁的 ORDER BY COALESCE(col, 999999) 隐含严重风险:
- 数值型字段填极值,可能与真实数据冲突(如真有
price = 999999,它就和NULL混排了) - 字符串字段用
COALESCE(name, 'ZZZZZ')同样危险——万一客户真叫'ZZZZZ',语义就乱了 - 类型隐式转换:DECIMAL 字段补整数可能触发警告或精度截断(尤其在严格模式下)
- 索引失效风险:对字段套函数后,多数数据库无法走原字段索引
除非你完全掌控数据分布且能保证极值永不出现,否则别碰这个方案。
SQL Server:用 CASE WHEN IS NULL 最稳妥
SQL Server 不支持 NULLS LAST,也不推荐 ISNULL() 填充——因为填充值参与实际比较,不是逻辑分组。
推荐写法(NULL 垫底):
ORDER BY CASE WHEN col IS NULL THEN 1 ELSE 0 END, col
注意点:
- 不能写成
SELECT ..., CASE WHEN col IS NULL THEN 1 ELSE 0 END AS sort_flag FROM ... ORDER BY sort_flag——部分 SQL Server 版本不支持在ORDER BY中引用SELECT列别名 - 如果
col是DATETIME,第二级排序仍可用col ASC,无需转字符串 - 该结构在跨数据库迁移(如从 SQL Server 迁到 PostgreSQL)时,只需把
CASE段替换成NULLS LAST,其余不变
真正容易被忽略的是:不同数据库对 NULL 的默认排序行为不一致,且这种不一致在 JOIN 或子查询中可能被掩盖。一旦上线后分页错位、前端列表跳变,往往要回溯好几层才定位到这一行 ORDER BY。










