where过滤只能整体筛选后单一计数,而case when在聚合函数中可并列统计多条件;推荐用sum(case when condition then 1 else 0 end),语义清晰且避免null误判。

WHERE过滤和CASE WHEN计数的区别在哪?
直接用 WHERE 只能统计满足单一条件的行数,而实际常需在一个查询里并列统计多个互斥或重叠的条件——比如「订单状态为已支付的有多少」「未支付但创建超24小时的有多少」「已取消的有多少」。这时候硬拆成多个 SELECT COUNT(*) 效率低、难维护;CASE WHEN 在聚合函数内配合 SUM 或 COUNT 才是标准解法。
COUNT(CASE WHEN ...) 和 SUM(CASE WHEN ...) 哪个更稳妥?
COUNT 对 NULL 不计数,SUM 对 NULL 当 0 处理,但两者在条件计数中行为一致——关键在于 CASE 的 ELSE 是否显式写 NULL。
- 推荐统一用
SUM(CASE WHEN condition THEN 1 ELSE 0 END):语义清晰,避免漏写ELSE导致隐式NULL被COUNT忽略 - 如果用
COUNT(CASE WHEN condition THEN 1 END),必须省略ELSE(否则ELSE NULL和默认NULL效果一样),靠COUNT自动跳过NULL - 别写
COUNT(CASE WHEN condition THEN 1 ELSE 0 END):0 会被COUNT计入,结果比预期多
多个条件嵌套时怎么避免逻辑覆盖?
常见错误是把互斥条件写成独立 CASE WHEN,导致同一行被重复计入多个统计项。正确做法是用单个 CASE 分支明确互斥关系,或用多个独立 CASE 但每个都自成判断闭环。
SELECT SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid_count, SUM(CASE WHEN status = 'pending' AND created_at
- 每个
CASE独立判断,行可同时满足多个条件(如某订单既是 pending 又超时) - 若要求严格互斥(一行只能进一个桶),需按优先级排序分支:
CASE WHEN paid THEN ... WHEN pending AND ... THEN ... ELSE ... END - 注意时区和时间函数兼容性:
NOW()在 PostgreSQL 是带时区的,MySQL 用NOW(),SQLite 用datetime('now')
性能上要注意哪些隐含开销?
CASE WHEN 本身不慢,但容易因误用放大扫描成本:
- 在大表上对未索引字段做条件判断(如
CASE WHEN user_name LIKE '%admin%' THEN ...)会强制全表扫描 - 避免在
CASE中调用复杂函数(如JSON_EXTRACT、正则匹配),尤其当该列数据量大时 - 如果只查某几个条件的计数,且对应字段有索引,考虑用
UNION ALL+ 多个带WHERE的COUNT(*),有时比单次扫描更快
真正难的是条件定义是否覆盖所有业务场景——比如「超24小时」用 created_at 还是 updated_at,空值要不要单独计数,这些得和业务方对齐,SQL 写得再准也救不了需求歧义。











