会,AVG()默认且必须忽略NULL值——这是ANSI SQL标准行为;它自动跳过NULL、以COUNT(col)为分母计算,全NULL时返回NULL;冗余WHERE过滤不仅无效,还破坏上下文;业务语义需明确区分NULL与0,用COALESCE兜底结果、NULLIF排除0值、COUNT()验证分母。

会,AVG() 默认且必须忽略 NULL 值——这是 ANSI SQL 标准行为,不是某个数据库的“兼容特性”。
AVG(col) 和 WHERE col IS NOT NULL 结果一样,但后者是冗余且危险的
你写 SELECT AVG(salary) FROM employees 和 SELECT AVG(salary) FROM employees WHERE salary IS NOT NULL,结果完全相同。但加 WHERE 会带来隐性风险:
- 如果同一查询里还要统计
COUNT(*)或关联其他字段(比如部门名),WHERE会整行过滤,破坏分组上下文 - 当后续要加入其他条件(如
status = 'active')时,WHERE salary IS NOT NULL容易被误删或遗漏,导致语义断裂 - 它传递错误信号:“我得手动清理 NULL”,掩盖了真正该关注的问题:业务上 NULL 到底代表什么
全 NULL 组返回 NULL 是正确行为,不是 bug
比如某部门所有员工 score 都是 NULL,AVG(score) 返回 NULL,不是 0,也不是报错。这符合数学定义——空集无平均值。
- 前端或 BI 工具报“空值渲染失败”?用
COALESCE(AVG(score), 0)在展示层兜底,不改变原始聚合逻辑 - 想彻底排除这类组?用
HAVING COUNT(score) > 0,因为COUNT(score)只统计非 NULL 行,而HAVING AVG(score) IS NOT NULL无效 - 别用
AVG(COALESCE(score, 0))代替——它把“未打分”强行算作“打了 0 分”,均值会被拉低,LTV、绩效等模型直接失真
想排除 0 值?用 NULLIF(),别用 WHERE
当 0 表示无效采集(如 API 耗时为 0、传感器离线占位符),而字段本身允许 NULL,直接 WHERE amount != 0 会丢弃整行。
- 正确做法:
AVG(NULLIF(amount, 0))——amount = 0时返回NULL,其余保持原值,AVG()自动跳过 - 这样保留了行结构,不影响同查询中的
COUNT(*)、MAX(amount)等其他聚合 - 负值(如温度变化量)必须保留时,
!= 0过滤会误删负数;NULLIF()不影响负值,更安全
光看 AVG() 结果永远不知道分母是多少
这是平均值失真最隐蔽的来源。同一列,AVG(x) 看起来合理,但背后可能是 3 行算的,也可能是 300 行算的。
- 必须搭配
COUNT(x)(非 NULL 行数)、COUNT(*)(总行数)、COUNT(NULLIF(x, 0))(非 NULL 且非 0 行数)一起查 - 例如:
SELECT AVG(x), COUNT(x), COUNT(*) FROM t—— 如果COUNT(x)远小于COUNT(*),说明数据缺失严重,不能直接拿平均值做决策 - 在子查询或视图中嵌套
AVG()时,外部WHERE可能已悄悄改变分母,最终层级务必校验COUNT()
真正难的不是怎么写 AVG(),而是说清楚 NULL 和 0 在你业务里分别代表什么——函数只是执行者,语义得人来定。

















