因为where在分组前过滤整行,会彻底排除不满足条件的记录,无法在同一行中并列统计多类条件;而case when在分组内逐行标记再聚合,可同时输出「男性人数」「女性人数」「未填写人数」等共存指标。

为什么直接用 COUNT + WHERE 不能替代 CASE WHEN 分组计数
因为 WHERE 是在分组前过滤整行,一旦加了条件,不满足的行就彻底消失了,无法和其它条件的结果共存于同一行输出。而真实需求常是:在同一 GROUP BY 结果中,并列统计「男性人数」「女性人数」「未填写人数」——这必须靠 CASE WHEN 在每行做条件标记,再由 COUNT 统计标记后的非 NULL 值。
COUNT(CASE WHEN ...) 的写法要点与常见错误
COUNT 对 NULL 不计数,所以 CASE WHEN 必须有 ELSE NULL(或干脆不写 ELSE),否则默认补 ELSE NULL 是安全的;但若误写成 ELSE 0,COUNT 会把 0 当有效值计入,导致结果虚高。
- ✅ 正确:
COUNT(CASE WHEN gender = 'M' THEN 1 END)(隐式ELSE NULL) - ❌ 错误:
COUNT(CASE WHEN gender = 'M' THEN 1 ELSE 0 END)(0 被计数) - ⚠️ 注意:
SUM(CASE WHEN ... THEN 1 ELSE 0 END)是等价替代写法,语义更直白,且不易错
和 SUM(CASE WHEN ...) 的性能与可读性对比
在绝大多数主流数据库(PostgreSQL、MySQL 8.0+、SQL Server、Oracle)中,COUNT(CASE ...) 和 SUM(CASE ...) 执行计划几乎一致,性能无差别。但可读性上:SUM 更贴近“条件计数”的本意,尤其当需要加权统计(如「VIP 用户计 2 点,普通用户计 1 点」)时,SUM 天然支持表达式,COUNT 就得绕弯。
- 标准计数场景二者任选,推荐用
SUM(CASE WHEN cond THEN 1 ELSE 0 END) - 需要加权或动态值时,只能用
SUM,例如:SUM(CASE WHEN level = 'vip' THEN 2 ELSE 1 END) - MySQL 5.7 及更早版本对
COUNT内嵌CASE支持略弱,建议统一用SUM避坑
多条件并列统计的实际 SQL 模板
假设表 users 有字段 status('active'/'inactive'/'pending')和 region('CN'/'US'/'JP'),要按地区分组,同时统计各状态人数:
SELECT region, SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) AS active_cnt, SUM(CASE WHEN status = 'inactive' THEN 1 ELSE 0 END) AS inactive_cnt, SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending_cnt FROM users GROUP BY region;
注意:所有 CASE 表达式都必须放在同一 SELECT 中,且不能在 GROUP BY 里引用别名(如不能写 GROUP BY active_cnt);另外,如果某组内全无匹配行,对应 SUM 返回 0 而非 NULL,符合多数业务预期。
最易被忽略的是空字符串或空格干扰——比如 gender = ' ' 或 status = '',这类数据会让 CASE 全部不命中,最终统计为 0 却不报错。上线前务必用 SELECT DISTINCT TRIM(status) FROM users 排查脏数据。










