包含 NULL 的 SUM 和 AVG
了解 AVG 为什么忽略 NULL,以及这会如何影响面试官期待的答案
包含 NULL 的 SUM 和 AVG 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。
AVG 中隐藏的陷阱
这是一个经典的面试问题,常常会让粗心的候选人失分:“假设有一个 salary 列,其中包含一些 NULL。AVG(salary) 会计算什么?这是否符合业务需求?”
诚实而准确的回答可以看出您是否理解聚合函数会忽略 NULL,而这会改变平均值的分母。如果在生产环境中弄错这一点,报告中的平均值可能会在不知不觉中偏高。
让我们把这种行为讲清楚。
示例数据
在整节课中使用这张 employees 表,其中包含可为 NULL 的 bonus 列:
- Alice,奖金 100
- Bob,奖金 200
- Carol,奖金 NULL
- Dan,奖金 300
共有四行,其中三行的奖金不为 NULL,一行为 NULL。我们将对这些数据执行 SUM 和 AVG,并观察 NULL 的处理方式。
SUM 忽略 NULL
SUM(bonus) 只会将不为 NULL 的值相加:100 + 200 + 300 = 600。NULL 所在的行不会产生任何贡献;它只是被跳过,而不是作为会影响计数的 0 参与计算。
实际效果就像 NULL 表示缺少值一样。SUM 遇到 NULL 不会报错,并且只有在所有输入都为 NULL 时才会返回 NULL。
SELECT SUM(bonus) AS total_bonus
FROM employees;
-- returns 600AVG 同样忽略 NULL
AVG(bonus) 是关键所在。它计算的是不为 NULL 的值之和除以不为 NULL 的值的数量:600 / 3 = 200。
分母是 3,而不是 4。NULL 所在的行既不会计入分子,也不会计入除数。这正是 AVG 可能令人意外的原因:它计算的是现有值的平均值,而不是所有行的平均值。
SELECT AVG(bonus) AS avg_bonus
FROM employees;
-- 600 / 3 = 200, NOT 600 / 4 = 150分母为何重要
假设在业务上,NULL 奖金表示“没有获得奖金”,也就是 0。那么业务上正确的平均值应为 600 / 4 = 150,但 AVG(bonus) 报告的是200。
面试中的正确回答是:“AVG 会忽略 NULL,因此它计算的是有奖金员工的平均值。如果 NULL 表示 0,我就必须先将 NULL 转换为 0。”能够说清这种差异,正是获得这一分的关键。
使用 COALESCE 将 NULL 转为 0
如果要将 NULL 当作 0,并计算所有行的平均值,请将列包装在 COALESCE(bonus, 0) 中。这样每一行都有数值,分母就会变为 4。
结果为 600 / 4 = 150。要点是:AVG(col) 和 AVG(COALESCE(col, 0)) 回答的是不同的业务问题。请有意识地进行选择。
SELECT AVG(COALESCE(bonus, 0)) AS avg_over_all
FROM employees;
-- 600 / 4 = 150AVG = SUM / COUNT:请谨慎
一个有用的等式是:AVG(col) 等于 SUM(col) / COUNT(col) — 请注意是 COUNT(col),而不是 COUNT(*),因为 AVG 和这个 COUNT 都会跳过 NULL。
如果错误地写成 SUM(col) / COUNT(*),得到的就是所有行的平均值(这里是 150),与 AVG 的结果(200)不同。面试官有时会要求您手动还原 AVG,以确认您选择了正确的 COUNT。
SELECT
AVG(bonus) AS builtin_avg, -- 200
SUM(bonus) * 1.0 / COUNT(bonus) AS manual_avg, -- 200
SUM(bonus) * 1.0 / COUNT(*) AS over_all_rows -- 150
FROM employees;整数除法陷阱
手动计算平均值时有一个隐蔽的错误:在许多数据库中,两个整数相除会执行整数除法,从而截断小数部分。7 / 2 可能得到 3,而不是 3.5。
AVG 通常会返回小数,但如果您使用整数列通过 SUM / COUNT 重新计算,就可能丢失精度。请先乘以 1.0,或先将其转换为小数类型。
SELECT
SUM(bonus) / COUNT(bonus) AS maybe_truncated,
SUM(bonus) * 1.0 / COUNT(bonus) AS precise
FROM employees;所有值都为 NULL 时
这是面试官喜欢考查的边界情况:如果所有值都为 NULL,或者筛选条件没有匹配任何行,会怎样?
- 当没有不为 NULL 的输入时,
SUM会返回 NULL(而不是 0)。 AVG也会返回 NULL,因为除以 0 个值没有定义。- 相比之下,
COUNT会返回 0。
如果需要数值默认值,请将结果包装在 COALESCE(SUM(col), 0) 中。
SELECT COALESCE(SUM(bonus), 0) AS safe_total
FROM employees
WHERE 1 = 0; -- no rows: returns 0, not NULL按组计算平均值
同样的 NULL 规则也适用于 GROUP BY。每个组的 AVG 都会除以该组中不为 NULL 的值的数量。如果某个组的奖金全部为 NULL,那么该组的 AVG 就会得到 NULL。
因此,当您看到出乎意料的按部门统计的平均值时,应先怀疑 NULL 使各组的分母变小,而不是先怀疑连接错误。
SELECT department, AVG(bonus) AS avg_bonus
FROM employees
GROUP BY department;如何表述这个答案
一个经过完善的面试回答可以这样说:“SUM 和 AVG 都会忽略 NULL。AVG 除以不为 NULL 的值的数量,因此 NULL 实际上会使分母变小。如果 NULL 应当计为 0,我会在聚合之前使用 COALESCE 将其转换为 0;否则,平均值只反映那些有值的行。”
这一句话同时体现了正确性、业务理解和解决方法。
快速检查
将这条规则应用到示例数据上。
小结
SUM 和 AVG 处理 NULL 时的要点:
- 两者都会完全忽略 NULL。
AVG(col)=SUM(col) / COUNT(col)— 分母不包含 NULL。- 当 NULL 表示 0 且应当参与计算时,请使用
COALESCE(col, 0)。 - 全部为 NULL 或没有行的输入会使 SUM 和 AVG 返回 NULL(COUNT 返回 0)。
- 手动重新计算 AVG 时,请注意整数除法。
下一部分:MIN、MAX 以及对非数值数据进行聚合。
常见问题解答
「包含 NULL 的 SUM 和 AVG」课时是免费的吗?
是的 — 「包含 NULL 的 SUM 和 AVG」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。
「包含 NULL 的 SUM 和 AVG」这节课中我会学到什么?
了解 AVG 为什么忽略 NULL,以及这会如何影响面试官期待的答案 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Interview Prep 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「包含 NULL 的 SUM 和 AVG」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Interview Prep 课中编写并运行代码吗?
能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- COUNT(*)、COUNT(column) 与 COUNT(DISTINCT)
- 包含 NULL 的 SUM 和 AVG
- MIN、MAX 与非数值汇总
- 不使用 GROUP BY 的汇总