在数据库查询的实际工作中,经常需要根据某个数值字段的区间范围进行分组统计,比如按照成绩划分优秀、良好、及格、不及格四个等级统计人数,或者按照订单金额划分不同消费层级统计用户数量。这类需求可以通过CASE WHEN条件判断结合SUM聚合函数高效实现,不需要多次查询数据库再手动汇总结果。

核心实现逻辑
CASE WHEN的作用是对每条记录的指定字段进行条件判断,返回对应的分段标识,而SUM函数可以配合条件判断统计符合某个分段条件的记录数量。基本思路是:先用CASE WHEN为每个记录匹配对应的分段标签,再用SUM函数对每个分段的记录数进行累加。
这里的SUM函数通常会结合CASE WHEN使用,当记录符合目标分段条件时返回1,否则返回0,SUM求和的结果就是该分段的记录总数。具体语法结构如下:
-- 基础语法结构
SELECT
SUM(CASE WHEN 条件1 THEN 1 ELSE 0 END) AS 分段1数量,
SUM(CASE WHEN 条件2 THEN 1 ELSE 0 END) AS 分段2数量,
...
FROM 表名;
实际场景示例
场景1:学生成绩分段统计
假设有一张student_score表,包含student_id(学生ID)和score(考试成绩)两个字段,现在需要统计成绩在90分及以上、80-89分、60-79分、60分以下四个区间的学生人数。
对应的SQL查询语句如下:
SELECT
SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END) AS 优秀人数,
SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END) AS 良好人数,
SUM(CASE WHEN score >= 60 AND score < 80 THEN 1 ELSE 0 END) AS 及格人数,
SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS 不及格人数
FROM student_score;
执行上述语句后,会返回一行结果,包含四个分段对应的人数,不需要额外进行分组操作,所有统计结果会直接在一行中展示。
场景2:用户消费金额分段统计
假设有一张user_order表,包含user_id(用户ID)和order_amount(订单金额)两个字段,现在需要统计消费金额在1000元以上、500-1000元、100-500元、100元以下四个区间的用户数量,注意同一个用户可能有多个订单,需要先按用户汇总总消费金额再统计。
对应的SQL查询语句如下:
-- 先按用户汇总总消费金额,再进行分段统计
WITH user_total_amount AS (
SELECT user_id, SUM(order_amount) AS total_amount
FROM user_order
GROUP BY user_id
)
SELECT
SUM(CASE WHEN total_amount >= 1000 THEN 1 ELSE 0 END) AS 高消费用户数,
SUM(CASE WHEN total_amount >= 500 AND total_amount < 1000 THEN 1 ELSE 0 END) AS 中高消费用户数,
SUM(CASE WHEN total_amount >= 100 AND total_amount < 500 THEN 1 ELSE 0 END) AS 中低消费用户数,
SUM(CASE WHEN total_amount < 100 THEN 1 ELSE 0 END) AS 低消费用户数
FROM user_total_amount;
进阶用法:结合GROUP BY实现多维度分段统计
如果需要按照其他维度(比如班级、地区)分别进行分段统计,可以结合GROUP BY子句实现。比如还是学生成绩的场景,现在需要统计每个班级的各分数段人数。
对应的SQL查询语句如下:
SELECT
class_id AS 班级ID,
SUM(CASE WHEN score >= 90 THEN 1 ELSE 0 END) AS 优秀人数,
SUM(CASE WHEN score >= 80 AND score < 90 THEN 1 ELSE 0 END) AS 良好人数,
SUM(CASE WHEN score >= 60 AND score < 80 THEN 1 ELSE 0 END) AS 及格人数,
SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS 不及格人数
FROM student_score
GROUP BY class_id;
执行后会根据class_id分组,每个班级返回一行对应的各分段人数统计结果。
注意事项
- 分段条件的区间边界要定义清晰,避免出现重叠或者遗漏的情况,比如相邻区间可以用<和>=搭配,保证每个数值只会匹配到一个分段。
- 如果统计的字段可能存在NULL值,需要在CASE WHEN中添加对NULL值的处理,比如NULL值统一归为某个分段,或者排除NULL值记录。
- SUM函数中的CASE WHEN返回的是数值类型,如果不需要统计数量,也可以返回其他字段的值,实现分段求和的需求,比如统计每个分数段的订单总金额。
如果需要同时返回分段标识和对应的统计结果,也可以先通过CASE WHEN生成分段标签,再外层嵌套查询用GROUP BY分组统计,示例如下:
SELECT
score_level AS 分数段,
COUNT(*) AS 人数
FROM (
SELECT
CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 80 THEN '良好'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END AS score_level
FROM student_score
) t
GROUP BY score_level;
这种写法会返回多行结果,每一行对应一个分段标签和对应的人数,适合需要分段结果按行展示的场景。