条件聚合:一次扫描计算多项指标
把重复子查询改为 SUM(CASE WHEN),让指标口径集中且可扩展。
问题与判断方法
为每个状态编写一条标量子查询虽然直观,但每增加一个指标就重复读取同一张表,筛选条件也容易在复制时发生口径漂移。报表字段越多,这种写法越难统一维护。
条件聚合在一次 GROUP BY 或全表聚合中计算多项指标:CASE WHEN 命中时贡献 1,否则贡献 0。所有指标共享同一输入集合,公共 WHERE 只写一次,也更容易一起核对。
要区分“行数”和“金额”等不同聚合目标,并为 NULL 指定 ELSE。数据量很小或子查询使用完全不同索引时,合并不一定更快;最终仍要查看目标 MySQL 的计划和读行数。
示例
示例数据表
表名:
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;优化前运行结果
| paid_count | cancelled_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;优化后运行结果
| paid_count | cancelled_count |
|---|---|
| 2 | 1 |
为什么这样更好:两个结果都是 paid=2、cancelled=1;推荐写法把两项指标放在同一次聚合中。
这篇内容是否清楚?
感谢反馈,我们会把它用于后续内容复核。