CASE WHEN 是SQL中实现数值区间分组最通用可控的方式,需注意边界包含性、NULL处理、GROUP BY必须重复完整CASE表达式、避免ELSE遗漏,并优先在WHERE中过滤以提升性能。

用 CASE WHEN 实现数值区间分组,核心是写对条件边界
直接结论:SQL 中没有原生的“按范围分组”语法,CASE WHEN 是最通用、最可控的方式。关键不是套模板,而是理清边界是否包含端点、空值怎么处理、以及 GROUP BY 必须引用 CASE 表达式本身(不能只写别名)。
WHERE 和 GROUP BY 里都得写完整的 CASE 表达式
很多人在 GROUP BY 里直接写 age_group 别名,结果报错 column "age_group" does not exist。因为 SQL 标准要求 GROUP BY 必须基于 SELECT 列的原始表达式,而不是别名(除非用子查询或 CTE)。
正确写法示例(PostgreSQL / MySQL 8.0+ / SQL Server):
SELECT
CASE
WHEN score < 60 THEN 'F'
WHEN score < 70 THEN 'D'
WHEN score < 80 THEN 'C'
WHEN score < 90 THEN 'B'
ELSE 'A'
END AS grade,
COUNT(*)
FROM students
GROUP BY
CASE
WHEN score < 60 THEN 'F'
WHEN score < 70 THEN 'D'
WHEN score < 80 THEN 'C'
WHEN score < 90 THEN 'B'
ELSE 'A'
END;
- 必须把整个
CASE表达式完整复制到GROUP BY中 - 如果还带
WHERE score IS NOT NULL,记得先过滤掉空值——否则CASE会返回NULL,导致单独一组 - 边界用
而非 <code> 是为了防止重叠;若用闭区间(如 <code>BETWEEN 70 AND 79),要确保区间不交叉
处理 NULL 和越界值时,ELSE 不可省略
漏写 ELSE 是高频错误。一旦某行数据不满足任何 WHEN 条件(比如 score 为 NULL,或值超出所有范围),整行在分组中就变成 NULL 组——容易被忽略,但可能占很大比例。
-
ELSE 'Unknown'比留空更安全,能暴露数据质量问题 - 如果业务上不允许越界值,建议先用
WHERE过滤,再分组,避免ELSE成为兜底黑洞 - MySQL 中
CASE对NULL比较特殊:WHEN score = NULL永远不成立,必须用WHEN score IS NULL
性能注意:范围字段最好有索引,但 CASE 本身无法走索引
CASE WHEN 是计算列,数据库无法对其直接使用索引。如果分组前需要先筛选大范围(比如只看 score > 50 的记录),务必把条件写进 WHERE,而不是全量扫描后靠 CASE 分类。
- 低效写法:
CASE WHEN score > 50 AND score —— 所有行都参与计算 - 高效写法:
WHERE score IS NOT NULL AND score >= 0 AND score ,再分组 - 如果频繁按同一套区间查,考虑增加一个物化列(如 PostgreSQL 的
GENERATED ALWAYS AS)并建索引
SELECT * 看几行 CASE 输出,确认每条数据都进了预期的桶里,再加 GROUP BY。

















