sum函数自动忽略null值,不报错也不当0处理;整列null或无匹配行时返回null,需用coalesce(sum(col), 0)确保返回0,或用sum(coalesce(col, 0))将每行null转0后再求和。

NULL值会让SUM直接忽略,但别误以为它“自动转0”
SUM本身对NULL是安全的——它会跳过NULL行,只累加非NULL数值。这点和AVG、COUNT(*)行为一致。但常见误解是:以为SUM(col)遇到全NULL时会返回0,实际返回NULL。比如SELECT SUM(salary) FROM employees WHERE dept = 'nonexistent',结果就是NULL,不是0。
如果你需要“空集也返回0”,得显式处理:
- 用
COALESCE(SUM(col), 0)最常用,兼容 MySQL / PostgreSQL / SQL Server - SQLite 用
IFNULL(SUM(col), 0) - Oracle 可用
NVL(SUM(col), 0)
想把字段里的NULL先转成0再求和?用COALESCE或IFNULL包裹列
有时候业务逻辑要求:字段为NULL就当0参与计算(比如补贴金额未填=0元)。这时不能只包SUM,而要包在列上:
SELECT SUM(COALESCE(bonus, 0)) FROM employees;
错误写法:SUM(COALESCE(bonus, 0))是对的,但COALESCE(SUM(bonus), 0)是错的逻辑——后者只在整列都NULL时补0,而前者确保每个NULL都先变0再加。
- MySQL 还支持
IFNULL(bonus, 0),语义相同 - PostgreSQL 不支持
IFNULL,必须用COALESCE - 注意嵌套顺序:
SUM(COALESCE(x, 0))≠COALESCE(SUM(x), 0),二者解决的问题完全不同
GROUP BY中遇到NULL分组,SUM照常工作,但分组键本身要注意
如果按一个可能为NULL的字段分组(比如category),NULL会被当作一个独立分组。例如:
SELECT category, SUM(amount) FROM sales GROUP BY category;
会得到一行category = NULL及其对应SUM值(即所有category为NULL的amount之和)。
- 若不想让
NULL单独成组,可提前过滤:WHERE category IS NOT NULL - 若想把
NULL归入某类(如“未知”),可用COALESCE(category, 'Unknown')作为分组表达式 -
SUM在每个分组内仍只累加该组内非NULL值,不受分组键NULL影响
性能与索引:加COALESCE后可能无法走索引
如果写SUM(COALESCE(price, 0))且price上有索引,多数数据库(如 MySQL 8.0+、PostgreSQL)无法直接利用该索引加速聚合——因为COALESCE改变了列的原始值表达式。
- 纯
SUM(price)在有索引时,优化器可能用索引快速扫描(尤其覆盖索引场景) - 一旦加上函数包装,基本退化为全表扫描,除非你建了函数索引(如 PostgreSQL 的
CREATE INDEX ON t ((COALESCE(price, 0)))) - 高频查询且
NULL极少时,考虑清洗数据:用UPDATE ... SET price = 0 WHERE price IS NULL,再建普通索引
真正容易被忽略的是:函数包装带来的隐式类型转换风险。比如COALESCE(num_col, '0')把数字和字符串混用,某些数据库会报错或静默转类型,务必确认两边类型一致。











