必须用IS NULL;= NULL永远返回FALSE,查不到任何记录。NULL在GROUP BY中自动聚为一组,若需语义化归类(如“未知”),应使用COALESCE或CASE统一处理分组键与SELECT表达式。

WHERE条件里用= NULL还是IS NULL?
绝大多数统计不准的起点,是把NULL当成普通值去比较。SQL里= NULL永远返回FALSE(不是TRUE也不是NULL),哪怕字段真为NULL也查不到。必须用IS NULL或IS NOT NULL。
-
WHERE status = NULL→ 什么也查不出来,别这么写 -
WHERE status IS NULL→ 正确匹配空值 - 聚合函数如
COUNT()默认忽略NULL,但COUNT(*)不忽略——这点常被误读
GROUP BY遇到NULL会合并成一组吗?
会。所有NULL在GROUP BY中被视为相同值,自动归为同一组。如果你本意是把NULL单独标记为“未知”或“未填”,直接GROUP BY column会导致它和其它真实值混在一起统计。
- 想区分空值和其他值:改用
GROUP BY COALESCE(column, 'N/A') - 注意
COALESCE第一个非NULL参数类型要和字段兼容,否则可能隐式转换出错 - 某些数据库(如MySQL)对
GROUP BY严格模式下,若SELECT里有非分组字段又没聚合,会报错——这时NULL字段更易暴露问题
LEFT JOIN后ON条件写错导致NULL被过滤
这是报表漏数的高发场景。比如LEFT JOIN orders ON users.id = orders.user_id本该保留所有用户,但如果在WHERE里加了orders.status = 'paid',就会把orders为NULL的用户行整个过滤掉——因为NULL = 'paid'结果是UNKNOWN,被当作FALSE处理。
- 把过滤条件从
WHERE挪到ON子句:LEFT JOIN orders ON users.id = orders.user_id AND orders.status = 'paid' - 如果必须在
WHERE里判断NULL,记得显式写出:WHERE orders.status = 'paid' OR orders.status IS NULL - 用
EXPLAIN看执行计划,确认rows数是否符合预期——JOIN后行数突降往往就是NULL被误杀
ORDER BY里NULL排前面还是后面?
不同数据库默认行为不一致:MySQL把NULL排最前,PostgreSQL排最后,SQL Server按ANSI标准默认排最前但可配置。报表排序错乱、TOP N取数偏差,常源于此。
- 显式控制顺序:
ORDER BY column ASC NULLS FIRST(PostgreSQL/Oracle支持) - 兼容写法:
ORDER BY CASE WHEN column IS NULL THEN 0 ELSE 1 END, column - 前端分页时尤其要注意——第一页数据看起来“少了一截”,很可能是
NULL全被挤到末尾或开头,而分页OFFSET跳过了它们
实际查问题时,先用SELECT COUNT(<em>), COUNT(column), COUNT(</em>) - COUNT(column) FROM table快速确认空值比例;再逐层检查JOIN、WHERE、GROUP BY里对NULL的处理逻辑。最麻烦的不是空值本身,而是它在不同上下文里表现不一致——同一个NULL,在JOIN里是缺失关联,在WHERE里是逻辑假,在ORDER BY里是排序幽灵。

















