You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效用SQL按程序分组统计各状态行数并转列为列?

问题描述

我有一个程序表,表结构及数据如下:

ID程序(Program)经办人(AssignedPerson)状态(Status)
1Sample Program APerson A已完成(Done)
2Sample Program APerson B已取消(Cancelled)
3Sample Program APerson C未启动(Not Started)
4Sample Program BPerson A已完成(Done)
5Sample Program BPerson C未启动(Not Started)
6Sample Program CPerson B已完成(Done)

需要对该表进行汇总,生成按唯一程序分组的各状态行数统计结果,目标表结构及数据如下:

程序(Program)已完成(Done)已取消(Cancelled)未启动(NotStarted)
Sample Program A111
Sample Program B11
Sample Program C1

**实现该需求的最高效方式是什么?**我担心使用子查询会导致查询缓慢,想了解是否存在更优的实现方案?


最优实现方案

最高效的方式是使用条件聚合(CASE WHEN + GROUP BY),这种方式仅需扫描一次原始表,避免了子查询多次扫描表的性能损耗,是这类行转列统计场景的最优解。

示例SQL代码(以MySQL为例)

SELECT
    `程序(Program)`,
    SUM(CASE WHEN `状态(Status)` = '已完成(Done)' THEN 1 ELSE 0 END) AS `已完成(Done)`,
    SUM(CASE WHEN `状态(Status)` = '已取消(Cancelled)' THEN 1 ELSE 0 END) AS `已取消(Cancelled)`,
    SUM(CASE WHEN `状态(Status)` = '未启动(Not Started)' THEN 1 ELSE 0 END) AS `未启动(NotStarted)`
FROM
    程序表
GROUP BY
    `程序(Program)`;

性能优势说明

  • 子查询方案通常需要为每个状态单独查询一次表(比如3个子查询就扫3次表),而条件聚合只需要一次全表扫描,数据量越大性能差距越明显。
  • 可以通过在程序(Program)和状态(Status)字段上建立联合索引(INDEX idx_program_status (程序(Program), 状态(Status))),进一步优化查询速度,让数据库直接通过索引完成分组和统计,无需回表。

其他数据库等价实现

如果使用支持PIVOT语法的数据库(如SQL Server、Oracle),也可以用PIVOT函数,本质和条件聚合逻辑一致,性能相当:

-- SQL Server 示例
SELECT
    [程序(Program)],
    [已完成(Done)],
    [已取消(Cancelled)],
    [未启动(Not Started)] AS [未启动(NotStarted)]
FROM
    程序表
PIVOT (
    COUNT(ID)
    FOR [状态(Status)] IN ([已完成(Done)], [已取消(Cancelled)], [未启动(Not Started)])
) AS PivotTable;

内容的提问来源于stack exchange,提问作者user3035024

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 19:25:16