SQLPathLab
SQL 实战指南 · MySQL 8.0

条件聚合:一次扫描计算多项指标

把重复子查询改为 SUM(CASE WHEN),让指标口径集中且可扩展。

问题与判断方法

为每个状态编写一条标量子查询虽然直观,但每增加一个指标就重复读取同一张表,筛选条件也容易在复制时发生口径漂移。报表字段越多,这种写法越难统一维护。

条件聚合在一次 GROUP BY 或全表聚合中计算多项指标:CASE WHEN 命中时贡献 1,否则贡献 0。所有指标共享同一输入集合,公共 WHERE 只写一次,也更容易一起核对。

要区分“行数”和“金额”等不同聚合目标,并为 NULL 指定 ELSE。数据量很小或子查询使用完全不同索引时,合并不一定更快;最终仍要查看目标 MySQL 的计划和读行数。

示例

示例数据表

表名:orders
orders
status
paid
pending
paid
cancelled

优化前 / 不推荐

SELECT (SELECT COUNT(*) FROM orders WHERE status = 'paid') AS paid_count, (SELECT COUNT(*) FROM orders WHERE status = 'cancelled') AS cancelled_count;

优化前运行结果

result
paid_countcancelled_count
2 1

优化后 / 推荐

SELECT SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid_count, SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_count FROM orders;

优化后运行结果

result
paid_countcancelled_count
2 1

为什么这样更好:两个结果都是 paid=2、cancelled=1;推荐写法把两项指标放在同一次聚合中。

这篇内容是否清楚?