sum()返回null而非0,因空结果集、全null列或无匹配行;需用coalesce(sum(col), 0)确保数值,且非聚合字段必须出现在group by中。

直接用 SUM() 就能算总和,但返回 NULL 而不是 0
这是最常踩的坑:查不到数据、整列是 NULL 或者过滤后没匹配行时,SUM() 一律返回 NULL,不是 0。前端直接取值或做加法会出错(比如 JavaScript 的 NULL + 100 是 NaN)。
- 想确保结果是数字,必须显式处理:
COALESCE(SUM(amount), 0)或 MySQL 下用IFNULL(SUM(amount), 0) -
SUM()自动跳过NULL值,不需要额外写WHERE amount IS NOT NULL - 如果字段本身允许
NULL,且业务上“无记录”和“金额为 0”含义不同,就别盲目COALESCE——否则会模糊语义
SUM() 必须配合 GROUP BY 才能混用其他字段
只要 SELECT 里有 SUM(),其他非聚合字段(比如 user_id、category)就必须出现在 GROUP BY 中,否则 MySQL 5.7+、PostgreSQL 等直接报错:Expression not in GROUP BY。
- 正确写法:
SELECT user_id, SUM(amount) FROM orders GROUP BY user_id - 错误写法:
SELECT user_id, name, SUM(amount) FROM orders GROUP BY user_id(name没聚合也没分组) - 如果真要带
name,得确认它和user_id是一一对应关系,否则应改用MAX(name)或MIN(name),但语义需自洽
条件求和别写子查询,用 CASE WHEN 套 SUM()
想算“已支付订单金额总和”或“某类商品销量”,直接在 SUM() 里嵌套 CASE WHEN,而不是写相关子查询——后者在多行结果下性能极差。
- 推荐:
SUM(CASE WHEN status = 'paid' THEN amount END)(ELSE省略即可,NULL会被SUM忽略) - 避免:
(SELECT SUM(amount) FROM orders o2 WHERE o2.order_id = o1.order_id AND o2.status = 'paid')(每行都触发一次子查询) - 注意:MySQL 8.0+、PostgreSQL、SQL Server 都支持这种写法;SQLite 也支持,但旧版本窗口函数受限
WHERE 和 HAVING 别搞混,时机完全不同
WHERE 在分组前筛行,HAVING 在 SUM() 算完之后筛组。写反了要么查不到数据,要么语法报错。
- 先筛再聚合:
WHERE product_type = 'electronics'放在GROUP BY前 - 筛聚合结果:
HAVING SUM(amount) > 1000必须放在GROUP BY后,且不能用别名(如HAVING total > 1000不通用) -
WHERE SUM(amount) > 1000是非法写法,数据库直接拒绝执行
NULL 返回值和 GROUP BY 字段完整性——这两点一错,轻则结果不对,重则查询失败。











