CASE WHEN必须同时出现在SELECT和GROUP BY中且表达式完全一致,别名不可用于GROUP BY;主流数据库均不支持直接在GROUP BY中写原始字段区间条件如age BETWEEN 18 AND 25。

CASE WHEN 必须出现在 SELECT 和 GROUP BY 中且表达式完全一致
直接在 GROUP BY 里写 age BETWEEN 18 AND 25 会报错——所有主流数据库(MySQL、PostgreSQL、SQL Server)都不支持这种语法。分段统计本质是“先构造虚拟维度,再按该维度聚合”,所以 CASE WHEN 必须同时出现在 SELECT 列和 GROUP BY 子句中,且两个位置的表达式字面完全相同。
- 别名不能用于
GROUP BY:写成SELECT CASE WHEN age >= 18 THEN 'adult' END AS age_group FROM t GROUP BY age_group在 PostgreSQL 和 MySQL 8.0+ strict 模式下会失败;必须写成GROUP BY CASE WHEN age >= 18 THEN 'adult' END - MySQL 5.7 允许省略
GROUP BY表达式(隐式全表分组),但跨库脚本必须显式写出,否则在 PG 上直接报错 - 如果字段是字符串型数字(如
'25'),MySQL 可能自动转,PostgreSQL 会报类型不匹配错误,务必提前CAST(age AS INTEGER)
边界必须用左闭右开风格,且覆盖全集
用 score >= 60 和 score >= 80 并列,60–79 分的数据会被第一个分支捕获,没问题;但若写成 score > 60 和 score >= 80,60.5 就掉进缝隙。更危险的是漏掉 NULL 或负数。
- 推荐统一用
age >= 18 AND age 这种左闭右开写法,比 <code>BETWEEN 18 AND 24更可控 - 必须显式处理
age IS NULL,不能只靠ELSE;业务上“年龄未填”和“0岁”含义不同,混在一起会失真 - 末尾
ELSE 'other'不仅防漏,还能暴露异常值(比如age = -1或999)
SUM(CASE WHEN ... THEN 1 ELSE 0 END) 是人数统计的正确姿势
想一查出多个区间的数量,不能靠反复 WHERE 过滤重跑 SQL。真正的分段统计是对每行原始数据做独立判断,再汇总——CASE WHEN 必须嵌在聚合函数内部,作用于行级。
- ✅ 正确:
SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END) AS excellent_cnt - ❌ 错误:
CASE WHEN SUM(score) >= 90 THEN 1 ELSE 0 END—— 这是在对全表总分做判断,不是分段 -
ELSE 0必须显式写出,否则任一分支返回NULL都会让整列SUM结果为NULL - 统计金额时把
1换成字段名:SUM(CASE WHEN status = 'paid' THEN amount ELSE 0 END)
大数据量下别让 CASE WHEN 阻碍索引使用
当表有千万级数据,又在 WHERE 里写 CASE WHEN score > 85 THEN 'A' END = 'A',这条语句基本无法走索引——CASE 是计算列,优化器没法下推条件。
- 正确做法是把区间逻辑前置到
WHERE,再用CASE做标签:WHERE score IS NOT NULL先过滤,减少扫描量 - 对原始字段建索引比对
CASE表达式建索引有效得多;score字段上有索引,WHERE score >= 80就能用上 - 超过 5 段时,别硬堆
CASE WHEN;优先用WITH提前算好标签列,主查询只做聚合

















