avg() 默认忽略 null,需用 avg(coalesce(col, 0)) 或 case 实现“null 视为 0”的全量平均;误用 sum(col)/count(*) 会导致分母偏大、结果偏小;group by 下更须统一 null 语义。

AVG() 默认就忽略 NULL,但你要的是“不忽略”的全量平均数
SQL 标准里的 AVG() 确实自动跳过 NULL 值——这不是 bug,是规范行为。如果你需要把 NULL 当作 0 或其他值参与计算(即“真实全量平均数”,比如业务上约定缺失销量记为 0),就得手动干预,不能依赖 AVG() 直接出结果。
用 COALESCE 或 CASE 把 NULL 转成指定值再算平均
最常用也最直观的方式,是在 AVG() 的输入列上做预处理:
-
AVG(COALESCE(sales, 0)):把sales中的NULL全部转成0后求平均 -
AVG(CASE WHEN sales IS NULL THEN 0 ELSE sales END):逻辑更显式,适合复杂替换规则(比如按部门设不同默认值) - 注意:
COALESCE()返回第一个非NULL表达式,类型需兼容;若sales是DECIMAL,0会隐式转成同精度,一般没问题
误用 COUNT(*) / SUM() 自己手算容易翻车
有人想绕开 AVG(),写成 SUM(col) / COUNT(*),这很危险:
-
COUNT(*)统计所有行,包括col为NULL的行;但SUM(col)本身也忽略NULL—— 结果是分母偏大、结果偏小 - 正确手算等价形式是:
SUM(COALESCE(col, 0)) / COUNT(*),和上面AVG(COALESCE(...))语义一致 - 别信“
AVG()效率低所以自己算更快”——现代优化器对AVG(COALESCE(...))和手算基本生成相同执行计划
GROUP BY 场景下 NULL 处理逻辑必须统一
如果加了 GROUP BY,每个分组内 NULL 的解释要前后一致:
- 比如统计各城市平均订单金额,某城市有 3 条记录:
100,NULL,200,按“缺省为 0”算就是(100 + 0 + 200) / 3 = 100 - 但若混用:
AVG(sales)(忽略 NULL)得150,而AVG(COALESCE(sales, 0))得100,两个结果业务含义完全不同 - 务必在需求文档或注释里写明:此处“全量平均数”定义为“NULL 视为 0 参与计算”,避免后续人误读
真正麻烦的不是写法,而是团队对“NULL 代表什么”没有共识——函数只是执行工具,语义得靠人对齐。










