最稳写法是sum(case when)而非子查询或嵌套逻辑,因其天然适配聚合层级、不报错不漏数且仅扫描表一次;必须套入sum因sql先group by再聚合,单独case when会报错或返回不确定值;else 0不可省,否则null被sum跳过致统计遗漏;多条件并列统计应使用多个sum(case when),并前置where过滤;字符串匹配前需trim、upper统一处理,null和空字符串须显式判断。

直接用 SUM(CASE WHEN) 是最稳的路,别绕弯写子查询或嵌套多层逻辑——它天然适配聚合层级,不报错、不漏数、只扫一遍表。
为什么必须把 CASE WHEN 套进 SUM 里?
因为 SQL 执行顺序是先 GROUP BY,再算聚合值。单独写 CASE WHEN status = 'paid' THEN 1 END 在 SELECT 里,数据库会把它当“非分组字段 + 非聚合结果”,直接报错或返回不确定值。
-
CASE WHEN本身只是行级判断,不是聚合函数;只有被SUM、COUNT这类包裹后,才能在每组内完成“逐行判断→汇总求值” - 写成
COUNT(CASE WHEN ... THEN 1 END)能跑通,但语义弱:它靠忽略 NULL 来计数,而SUM(... ELSE 0)显式控制每一行贡献值,更可控 - MySQL 5.7+ 严格模式下,漏包聚合函数会直接触发
ERROR 1140
ELSE 0 到底能不能省?
不能省。不写 ELSE 默认补 ELSE NULL,而 SUM 会跳过 NULL —— 看似没报错,实则悄悄漏统计。
- 比如查“非北京用户数”:
SUM(CASE WHEN city != '北京' THEN 1 END),当city是NULL时,这一行既不进分支,也不被计入,结果少算 - 正确写法:
SUM(CASE WHEN city != '北京' THEN 1 ELSE 0 END),确保每行都明确贡献 0 或 1 - 如果原始字段(如
amount)可能为NULL,建议先COALESCE(amount, 0)再参与SUM
多个条件并列统计怎么写才高效?
一次查询里并列多个 SUM(CASE WHEN) 是标准做法,数据库只扫描源表一次,但 WHERE 过滤必须前置,否则白跑大量无关行。
- ✅ 推荐:
SELECT SUM(CASE WHEN type = 'cash' THEN amount ELSE 0 END), SUM(CASE WHEN type = 'card' THEN amount ELSE 0 END) FROM orders WHERE status IN ('paid', 'shipped') - ❌ 避免:
WHERE status = 'paid'却在CASE WHEN里还判断type——过滤不彻底,性能浪费 - 别在同一个
CASE WHEN里混用跨时间维度字段(如create_time和pay_time),逻辑容易错位;需先用子查询打标,再聚合
字符串、空值、大小写导致匹配失败怎么办?
CASE WHEN 对值敏感,源数据若有空格、大小写混杂或 NULL,分支就匹配不上,结果直接变 NULL,你还以为“数据不存在”。
- 先查真实取值:
SELECT DISTINCT TRIM(UPPER(city)) FROM users - 比较前统一处理:
CASE WHEN TRIM(UPPER(city)) = 'BEIJING' THEN 1 ELSE 0 END -
NULL要单独判断:CASE WHEN city IS NULL THEN 1 WHEN city = '北京' THEN 0 ELSE 0 END
最易被忽略的是:字段本身含空字符串或 NULL 时,所有 = 判断都会失效,必须显式覆盖这些边界情况,否则统计永远对不上数。











