PostgreSQL数据透视表创建问题:SQL写法错误排查及替代方案咨询
嘿,我来帮你搞定这个PIVOT表的问题~
问题出在哪?
你当前的SQL写法核心问题是没对UserID做分组,也没用到聚合函数。
你写的CASE语句只是逐行判断产品类型并填充对应列,但每一行都会单独输出——正常来说,你原本的SQL跑出来的结果应该是每个用户对应三行,每行只有一列有QTY值,其他列是NULL(你描述的所有列都是同一个QTY值可能是笔误)。而你想要的是把同一用户的行合并成一行,这就必须用分组+聚合来实现。
修正后的基础写法
给UserID加上GROUP BY,再用MAX()(或者SUM(),这里每个用户每个产品只有一条数据,两者效果一样)来提取对应产品的有效QTY值:
SELECT UserID, MAX(CASE WHEN Product = 'A' THEN QTY END) AS A, MAX(CASE WHEN Product = 'B' THEN QTY END) AS B, MAX(CASE WHEN Product = 'C' THEN QTY END) AS C FROM public.table GROUP BY UserID ORDER BY UserID;
原理很简单:GROUP BY UserID把同一用户的所有行合并成一组,MAX()会忽略CASE语句返回的NULL值,只保留对应产品的QTY数值,这样就得到了每个用户一行、各产品QTY分列的结果。
更简洁的原生PIVOT写法(PostgreSQL 11+适用)
如果你用的是PostgreSQL 11及以上版本,可以直接用原生的PIVOT语法,代码更直观:
SELECT * FROM public.table PIVOT ( MAX(QTY) FOR Product IN ('A' AS A, 'B' AS B, 'C' AS C) ) AS pivot_result ORDER BY UserID;
同样因为每个用户每个产品只有一条记录,用SUM()替换MAX()也能得到一样的结果。
最终效果
不管用哪种写法,都能得到你想要的PIVOT表:
| UserID | A | B | C |
|---|---|---|---|
| 10 | 100 | 200 | 300 |
| 12 | 50 | 60 | 70 |
| 15 | 500 | 550 | 600 |
内容的提问来源于stack exchange,提问作者Galat
相关产品推荐
相关产品推荐

