在SQL Server的日常数据统计工作中,经常需要按照某个字段进行分组,同时统计组内满足不同条件的记录数量,比如按部门统计员工中正式工和实习工的人数,按订单日期统计不同支付方式的订单数量。这类需求如果使用多个查询分别统计再关联的方式实现,不仅代码冗余,还会增加数据库的执行开销,而COUNT配合CASE WHEN的模式可以高效解决这类问题。

COUNT(CASE WHEN...)模式的基本语法
COUNT函数本身是统计非空值的数量,当和CASE WHEN结合使用时,CASE WHEN会先对每一条记录的条件进行判断,符合条件时返回非空值,不符合时返回NULL,COUNT就会自动统计符合条件记录的数量,基本语法结构如下:
-- 基础语法结构
SELECT
分组字段,
COUNT(CASE WHEN 条件1 THEN 1 END) AS 条件1计数,
COUNT(CASE WHEN 条件2 THEN 1 END) AS 条件2计数
FROM 表名
GROUP BY 分组字段;
这里CASE WHEN的THEN后面可以返回任意非空值,比如1、'x'等,只要不是NULL,COUNT都会将其计入统计结果。如果条件不满足,CASE WHEN没有写ELSE的话默认返回NULL,不会被COUNT统计。
实际业务场景示例
场景一:按部门统计员工类型数量
假设有一张员工表Employee,包含字段dept(部门)、emp_type(员工类型,1代表正式工,2代表实习工)、emp_name(员工姓名),现在需要统计每个部门的正式工和实习工人数,使用COUNT(CASE WHEN...)模式的查询如下:
SELECT
dept AS 部门,
COUNT(CASE WHEN emp_type = 1 THEN 1 END) AS 正式工人数,
COUNT(CASE WHEN emp_type = 2 THEN 1 END) AS 实习工人数
FROM Employee
GROUP BY dept;
如果Employee表中有部门A共5人,其中3个正式工2个实习工,部门B共4人,1个正式工3个实习工,上述查询的结果会是:
| 部门 | 正式工人数 | 实习工人数 |
|---|---|---|
| 部门A | 3 | 2 |
| 部门B | 1 | 3 |
场景二:统计订单的不同状态数量
再比如订单表Orders包含字段order_date(订单日期)、order_status(订单状态,0待支付,1已支付,2已取消),需要按订单日期统计每天的待支付、已支付、已取消订单数量,查询代码如下:
SELECT
order_date AS 订单日期,
COUNT(CASE WHEN order_status = 0 THEN 1 END) AS 待支付订单数,
COUNT(CASE WHEN order_status = 1 THEN 1 END) AS 已支付订单数,
COUNT(CASE WHEN order_status = 2 THEN 1 END) AS 已取消订单数
FROM Orders
GROUP BY order_date;
使用注意事项
- CASE WHEN的条件判断要准确,避免逻辑错误导致统计结果偏差,比如条件中写错字段值或者比较符号。
- 如果需要对计数结果做进一步处理,比如只统计计数大于0的分组,可以在外层嵌套查询使用HAVING子句,COUNT(CASE WHEN...)的别名可以直接在HAVING中使用。
- 该模式支持多个条件组合判断,比如需要统计部门A中正式工的数量,可以写成
COUNT(CASE WHEN dept = '部门A' AND emp_type = 1 THEN 1 END),不需要额外嵌套子查询。 - 当条件比较复杂时,CASE WHEN也可以写成CASE 字段 WHEN 值 THEN 的形式,比如
COUNT(CASE emp_type WHEN 1 THEN 1 END),和上面的条件写法效果一致,可以根据场景选择更简洁的写法。
和传统方式的对比
如果使用传统方式实现上述部门统计需求,可能需要分别查询正式工和实习工的数量再关联,代码类似下面这样:
SELECT
t1.dept,
t1.正式工人数,
t2.实习工人数
FROM
(SELECT dept, COUNT(1) AS 正式工人数 FROM Employee WHERE emp_type = 1 GROUP BY dept) t1
LEFT JOIN
(SELECT dept, COUNT(1) AS 实习工人数 FROM Employee WHERE emp_type = 2 GROUP BY dept) t2
ON t1.dept = t2.dept;
对比可以看出,COUNT(CASE WHEN...)模式只需要一次全表扫描和分组,而传统方式需要两次扫描和分组,还要做表关联,代码更冗长,执行效率也更低,尤其是在数据量较大的场景下,性能差异会更明显。
SQL_ServerCOUNT_CASE_WHEN分组计数条件统计修改时间:2026-07-01 00:39:24