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

PostgreSQL:如何将GROUP BY聚合结果转为列展示(行转列)

这是很常见的**行转列(Pivot)**需求,不同数据库的实现方式略有不同,我给你整理了几种主流数据库的解决方案:

先明确你的数据场景

原始数据表 test_table

IDDayCount
1'1'1
1'2'2
1'2'7
2'2'4
2'2'3

你已完成的聚合结果

通过GROUP BY ID, Day你已经得到了分组后的Count总和:

SELECT ID, Day, SUM(Count) AS total_count 
FROM test_table 
GROUP BY ID, Day

结果:

IDDaytotal_count
1'1'1
1'2'9
2'2'7

实现期望行转列的方案

1. MySQL(无原生PIVOT,用条件聚合)

MySQL没有内置的PIVOT函数,最通用的方式是用条件聚合,通过CASE WHEN结合聚合函数实现:

SELECT 
    ID,
    SUM(CASE WHEN Day = '1' THEN Count ELSE 0 END) AS Day1,
    SUM(CASE WHEN Day = '2' THEN Count ELSE 0 END) AS Day2
FROM test_table
GROUP BY ID;

逻辑很直观:对每个ID,分别统计Day='1'和Day='2'的Count总和,没有对应Day的记录就返回0。

2. SQL Server(用原生PIVOT语法)

SQL Server支持原生的PIVOT语法,写法更简洁:

SELECT 
    ID,
    ISNULL([1], 0) AS Day1,
    ISNULL([2], 0) AS Day2
FROM (
    -- 先获取分组后的聚合结果
    SELECT ID, Day, SUM(Count) AS total_count
    FROM test_table
    GROUP BY ID, Day
) AS grouped_data
PIVOT (
    SUM(total_count)
    FOR Day IN ([1], [2])  -- 指定要转成列的Day值
) AS pivot_table;

用ISNULL把PIVOT返回的NULL替换成0,保证没有对应Day的ID显示0而非空值。

3. PostgreSQL(用crosstab函数)

PostgreSQL可以借助tablefunc扩展里的crosstab函数实现,需要先启用扩展:

-- 仅需执行一次,启用tablefunc扩展
CREATE EXTENSION IF NOT EXISTS tablefunc;

-- 执行行转列查询
SELECT 
    ID,
    COALESCE(Day1, 0) AS Day1,
    COALESCE(Day2, 0) AS Day2
FROM crosstab(
    'SELECT ID, Day, SUM(Count) FROM test_table GROUP BY ID, Day ORDER BY 1,2',
    'SELECT DISTINCT Day FROM test_table ORDER BY 1'
) AS ct(ID INT, Day1 INT, Day2 INT);

COALESCE的作用和ISNULL类似,把空值替换成0。


补充说明

如果你的Day取值是动态的(比如未来会新增Day3、Day4),静态写列名的方式就不适用了,这时候需要用动态SQL来自动生成对应的列,不同数据库的动态SQL写法有所差异,比如MySQL用预处理语句,SQL Server用EXEC或sp_executesql。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:09:34