在SQL的实际使用中,分组内条件比例统计是高频需求,比如统计每个班级中及格学生的占比、每个部门中绩效达标员工的比例等。传统的实现方式需要先分别统计分组总条数和符合条件的条数,再进行除法运算,步骤较多。而AVG(CASE WHEN)技巧可以简化这个过程,直接返回分组内的条件比例。
AVG(CASE WHEN)的实现原理
要理解这个技巧,需要先明确两个函数的特性:
CASE WHEN表达式会根据条件返回对应的值,当条件满足时返回1,不满足时返回0,这样每条记录都会对应一个0或1的标识值。AVG函数计算平均值时,会将所有值求和后除以总记录数,而0和1的平均值刚好等于1的数量除以总数量,也就是符合条件的比例。
因此将两者结合,就能直接得到分组内的条件比例,不需要额外的中间计算步骤。
基础使用示例
假设有一张学生成绩表student_score,结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| class_id | int | 班级ID |
| student_id | int | 学生ID |
| score | int | 考试成绩 |
现在需要统计每个班级中考试成绩大于等于60分的学生占比,使用AVG(CASE WHEN)的SQL语句如下:
-- 统计每个班级及格学生比例
SELECT
class_id,
-- 及格返回1,不及格返回0,平均值即为及格比例
AVG(CASE WHEN score >= 60 THEN 1 ELSE 0 END) AS pass_rate
FROM student_score
GROUP BY class_id;
执行上述语句后,会返回每个班级ID和对应的及格比例,结果值在0到1之间,如果需要百分比形式,可以乘以100再做格式化处理。
多条件统计场景
如果需要同时统计多个条件的比例,也可以在一个查询中使用多个AVG(CASE WHEN)表达式。比如同时统计每个班级的及格率和优秀率(成绩大于等于90分为优秀):
-- 同时统计及格率和优秀率
SELECT
class_id,
AVG(CASE WHEN score >= 60 THEN 1 ELSE 0 END) AS pass_rate,
AVG(CASE WHEN score >= 90 THEN 1 ELSE 0 END) AS excellent_rate
FROM student_score
GROUP BY class_id;
这样一次查询就能得到多个维度的条件比例,不需要多次查询或者关联子查询,效率更高。
注意事项
使用该技巧时需要注意几个问题:
- 如果分组内没有记录,AVG函数会返回NULL,需要根据实际情况使用
COALESCE函数处理空值。 - CASE WHEN的ELSE分支不能省略,否则不满足条件时会返回NULL,导致AVG计算结果不准确。
- 不同数据库对AVG函数的处理一致,该技巧在MySQL、PostgreSQL、SQL Server、Oracle等主流数据库中都可以正常使用。
如果需要处理空值情况,可以调整语句如下:
-- 处理分组无记录时的空值情况
SELECT
class_id,
COALESCE(AVG(CASE WHEN score >= 60 THEN 1 ELSE 0 END), 0) AS pass_rate
FROM student_score
GROUP BY class_id;
通过上述方式,就能稳定地得到每个分组内满足特定条件的比例,大幅简化SQL的编写逻辑,提升数据查询的效率。
SQLAVG_CASE_WHEN分组统计条件比例修改时间:2026-07-17 18:09:24