PostgreSQL数据透视表实现:如何按Segment分组返回单行结果?
问题描述
我有一张原始数据表,想要将其转换为如下结构的透视表:
| Segment | API | Mobile | Web |
|---|---|---|---|
| Enterprise | 1,739,410.3 | 3,459,504.5 | 4,661,960.09 |
| SMB | 410,281.84 | 939,104.25 | 1,247,303.96 |
| Startup | 2,621,454.13 | 5,702,420.6 | 7,898,458.36 |
但我使用以下查询语句时:
CASE WHEN channel = 'API' THEN sum(cost) END AS api, CASE WHEN channel = 'Mobile' THEN sum(cost) END AS mobile, CASE WHEN channel = 'Web' THEN sum(cost) END AS web
得到的结果是每个Segment对应多行含null值的记录:
| Segment | API | Mobile | Web |
|---|---|---|---|
| Enterprise | 1,739,410.3 | null | null |
| Enterprise | null | 3,459,504.5 | null |
| Enterprise | null | null | 4,661,960.09 |
| Enterprise | null | null | null |
| SMB | 410,281.84 | null | null |
| SMB | null | 939,104.25 | null |
| SMB | null | null | 1,247,303.96 |
| SMB | null | null | null |
| Startup | 2,621,454.13 | null | null |
| Startup | null | 5,702,420.6 | null |
| Startup | null | null | 7,898,458.36 |
| Startup | null | null | null |
请问如何修改查询,使每个Segment仅返回一行结果?
解决方案
问题出在SQL逻辑顺序错误且缺少分组语句,修改方式如下:
通用写法(适用于所有支持SQL的数据库)
将SUM函数包裹在CASE表达式外部,同时通过GROUP BY Segment按分组聚合结果:
SELECT Segment, SUM(CASE WHEN channel = 'API' THEN cost ELSE 0 END) AS api, SUM(CASE WHEN channel = 'Mobile' THEN cost ELSE 0 END) AS mobile, SUM(CASE WHEN channel = 'Web' THEN cost ELSE 0 END) AS web FROM 你的表名 GROUP BY Segment;
逻辑说明:
- 每条记录通过
CASE判断渠道,匹配则返回对应cost值,不匹配返回0(避免聚合后出现null) SUM函数对每个Segment下的渠道数据分类求和GROUP BY Segment确保每个Segment只生成一行聚合结果
简洁写法(支持PIVOT语法的数据库,如SQL Server、Oracle)
如果你的数据库支持PIVOT,可以用更直观的语法实现:
SELECT * FROM ( SELECT Segment, channel, cost FROM 你的表名 ) AS 源数据表 PIVOT ( SUM(cost) FOR channel IN ([API], [Mobile], [Web]) ) AS 透视结果表;
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

