avg()的分母是count(column)而非count(),会忽略null值,导致业务语义偏差;需显式兜底处理null并对照count(column)与count()验证分母。

因为AVG()不报错、不警告,却悄悄改变分母——你看到的“平均值”可能压根不是你要算的那个基数。
AVG() 的分母永远是 COUNT(column),不是 COUNT(*)
这是 ANSI SQL-92 标准行为,不是 MySQL 特有。只要列值为 NULL,那一行就从求和与计数两个环节同时消失。
-
AVG(score)等价于SUM(score) / COUNT(score),不是SUM(score) / COUNT(*) - 当 5 条记录里有 2 条
score IS NULL,COUNT(score)返回 3,COUNT(*)返回 5 - 业务上想算“全体用户平均付费”,但
AVG(amount)实际算的是“付费用户的平均金额”——差了一个量级
COALESCE(col, 0) 看似补全,实则扭曲语义
把 NULL 强制转成 0 并不等于“填默认值”,而是把“未知”篡改为“已知为零”,尤其在高 NULL 比例场景下偏差剧烈。
- 传感器表中
temperature IS NULL表示“设备离线”,填0后均值会被系统性拉低 -
AVG(COALESCE(amount, 0))分母仍是COUNT(amount),不是COUNT(*),所以它 ≠SUM(COALESCE(amount, 0)) / COUNT(*) - 真要按总人数摊薄,得写
SUM(COALESCE(amount, 0)) / COUNT(*),而不是套一层AVG()
全 NULL 组返回 NULL,应用层不兜底直接崩
比如查某用户历史评分:SELECT AVG(score) FROM ratings WHERE user_id = 123,若该用户从未打分,结果就是 NULL。
- Java 用
ResultSet.getDouble()直接取会抛SQLException - Python 中
row[0]是None,参与后续算术运算触发TypeError - 前端渲染时显示为空或
null字符串,而非预期的0或 “暂无数据” - 防御写法必须显式兜底:
IFNULL(AVG(score), 0)(MySQL)或COALESCE(AVG(score), 0)
最易被忽略的一点:你在视图或子查询里嵌套了 AVG(),外部再加 WHERE,分母已经不是原始表的 COUNT(*),也不是你直觉里的“这组该有多少人”——唯一靠谱的办法,是在最终 SELECT 里并列输出 AVG(x)、COUNT(x) 和 COUNT(*),三者对照着看。











