GROUP BY 配合 CASE WHEN 可实现连续数值的自定义分段统计,需用 CASE WHEN 构造离散标签再分组,注意 NULL 和边界值处理,WHERE 用于分组前过滤,HAVING 仅适用于聚合结果。

GROUP BY 配合 CASE WHEN 实现自定义数值分段
直接用 GROUP BY 无法对连续数值做区间划分,必须借助条件表达式构造分组键。最可靠、兼容性最好的方式是用 CASE WHEN 生成离散的分段标签,再对这个标签分组。
比如想把 score 字段按 [0,60)、[60,80)、[80,100] 分三档统计人数:
GROUP BY
-
FLOOR(value / 10) * 10可生成 [0,10), [10,20), [20,30)… 的左闭右开区间起点 -
ROUND(value, -1)(四舍五入到十位)适合中心对齐分桶,但边界行为要小心:比如ROUND(25, -1)= 30,ROUND(35, -1)= 40,25 和 35 被分到不同桶,而 24 和 26 却同属 20 桶 - 若需 [0,10], [11,20], … 这类整数闭区间,建议统一转成左闭右开逻辑处理,避免边界重复或遗漏
示例:按每 5000 元薪资分段统计
SELECT FLOOR(salary / 5000) * 5000 AS salary_range_start, COUNT(*) AS cnt FROM employee GROUP BY FLOOR(salary / 5000);
结果中 salary_range_start 是每段下界,如 0、5000、10000 —— 注意它只是标识,不代表真实数据范围是否覆盖整个区间。
WHERE 和 HAVING 对分段统计的影响容易混淆
过滤动作发生的时机决定了结果含义:
-
WHERE在分组前过滤原始行,影响哪些数据参与分段 -
HAVING在分组后过滤分组结果,影响最终返回哪些段
例如只统计「有效分数」(非 NULL 且 ≥ 0)的分段分布,必须用 WHERE score >= 0;如果想只显示人数 ≥ 5 的分段,则加 HAVING COUNT(*) >= 5。
常见错误:把本该放 WHERE 的条件误写进 HAVING,导致全表先分组再过滤,性能差且语义错误。比如 HAVING score >= 0 是非法的(score 不在聚合结果中),会报错 Invalid use of group function 或类似提示。
NULL 值和边界值必须显式处理
数值字段含 NULL 时,CASE WHEN score 不会匹配,该行默认进入 ELSE 分支 —— 这往往不是你想要的。同样,等于边界值(如 score = 60)时,score 为 false,会落入下一档,这点必须和业务规则对齐。
稳妥做法:
- 在
CASE开头加WHEN score IS NULL THEN '未知' - 用明确的区间写法,如
WHEN score BETWEEN 60 AND 79 THEN '中等',比多个更直观少错 - 测试边界数据:插入 score = 60、59.999、60.001 等值,确认分段逻辑符合预期
分段逻辑一旦上线,后续调整区间容易引发统计口径变更,建议把分段规则固化为视图或 CTE,避免多处硬编码。










