分段统计必须用CASE WHEN嵌套在SUM等聚合函数内,对每行原始数据做判断后累加;错误做法是WHERE过滤或聚合后判断,且必须显式写ELSE 0防NULL导致结果为空。

分段统计必须用 CASE WHEN 配合聚合函数,不能只靠 WHERE
直接在 WHERE 里加条件会过滤掉其他分段的数据,导致无法一查多段。真正要的是“每行都参与计算,但按规则归入不同桶”。CASE WHEN 在 SUM() 内部做行级判断,把布尔结果转成数值再累加,这才是分段统计的正确起点。
- 错误写法:
SELECT SUM(amount) FROM orders WHERE status = 'paid'—— 只能查一段,换一段就得重写查询 - 正确思路:每个分段都是一个独立的
SUM(CASE WHEN ... THEN 1 ELSE 0 END)或SUM(CASE WHEN ... THEN amount ELSE 0 END) - 注意
ELSE 0必须显式写出,否则NULL会让整列SUM结果变NULL
CASE WHEN 放在 SUM 里面,不是外面
位置错了结果就全歪了。有人写成 CASE WHEN SUM(...) > 100 THEN ...,这是对聚合后值做判断,不是分段统计。真正的分段逻辑必须作用于原始行,再交给 SUM 汇总。
- ✅ 正确:
SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END) AS excellent_count - ❌ 错误:
CASE WHEN SUM(score) >= 90 THEN 1 ELSE 0 END—— 这是在算全表总分是否 ≥ 90 - 如果要统计金额而非人数,把
1换成字段名,比如SUM(CASE WHEN status = 'shipped' THEN amount ELSE 0 END)
多个分段共存时,各 CASE WHEN 互不干扰,但要注意边界覆盖
每个 CASE WHEN 是独立表达式,SQL 会逐个计算。问题常出在区间没对齐,比如 < 60、>= 60 AND < 80、>= 80,漏掉等于号或重叠都会让数据进错桶。
- 常见翻车点:用
< 60和>= 60看似严丝合缝,但遇到NULL分数时,两个分支都不命中 → 必须加ELSE 0或单独处理IS NULL - 更稳的写法是穷举 +
ELSE 0:CASE WHEN score IS NULL THEN 0 WHEN score < 60 THEN 1 WHEN score < 80 THEN 1 ELSE 1 END - 别省略
ELSE,哪怕只是补个0,否则该段统计直接消失
性能和可读性:别堆太多 CASE WHEN,复杂逻辑建议提前落表或用 CTE
单条 SQL 里塞七八个 CASE WHEN 不仅难维护,MySQL 8.0 以前还可能因优化器限制拖慢执行。尤其当判断逻辑涉及子查询、函数或跨表关联时,先用 WITH 把分类标签算好,再聚合更清晰也更快。
- 简单分段(3–4 段):直接写没问题,例如统计订单状态分布
- 复杂分段(带业务规则、多字段组合、需复用):优先用
WITH生成中间标签列,主查询只做SUM和GROUP BY - MySQL 5.7 或低版本不支持
WITH?那就用派生表(FROM (SELECT ..., CASE...))替代,别硬扛超长CASE
CASE WHEN,但实际最容易卡在 NULL 处理、边界写错、以及把聚合后判断当成分段逻辑——这三个地方一错,结果就不可信。










