使用 PostgreSQL 创建数据透视表
Posted
技术标签:
【中文标题】使用 PostgreSQL 创建数据透视表【英文标题】:Create a pivot table with PostgreSQL 【发布时间】:2014-01-04 06:44:15 【问题描述】:假设我在 Postgres 中有一个名为 listings
的表,如下所示:
id neighborhood bedrooms price
1 downtown 0 256888
2 downtown 1 334000
3 riverview 1 505000
etc.
如何编写交叉表查询,将每间卧室的平均价格显示为列,将街区显示为行?
查询的输出应该是这样的(数字是组成的,列是卧室):
0 1 2 3
riverton 250000 300000 350000 -
downtown 189000 325000 - 450000
【问题讨论】:
【参考方案1】:首先用聚合函数avg()计算平均值:
SELECT neighborhood, bedrooms, avg(price)
FROM listings
GROUP BY 1,2
ORDER BY 1,2
然后按照此相关答案中的详细说明将结果提供给crosstab()
函数:
【讨论】:
@Avishai:(全功能)带有位置引用的语法简写,GROUP BY neighborhood, bedrooms
的缩写【参考方案2】:
在 Postgres 中构建数据透视表的最佳方式是 CASE 表达式。
SELECT neighborhood,
round(avg((CASE WHEN bedrooms = 0 THEN price END)), 2) AS "0",
round(avg((CASE WHEN bedrooms = 1 THEN price END)), 2) AS "1",
round(avg((CASE WHEN bedrooms = 2 THEN price END)), 2) AS "2",
round(avg((CASE WHEN bedrooms = 3 THEN price END)), 2) AS "3"
FROM listings
GROUP BY neighborhood;
对问题数据运行此操作会产生
NEIGHBORHOOD 0 1 2 3
-------------------- ---------- ---------- ---------- ----------
downtown 256888 334000 NULL NULL
riverview NULL 505000 NULL NULL
【讨论】:
这个使用 case 语句的特定示例是不正确的。声明round(avg((case when bedroom = 0 then price else 0 end)),2)
表示每间卧室超过 0 间的公寓在取平均值时被视为价格为 0 的 0 间卧室。
看,我在这里使用您的方法为我的转置/透视查询做了类似的方法。如果我 DONT 添加avg
函数(在这种情况下,让我们说bedroom
)Postgres 会抱怨并说bedroom
也需要与neighborhood
组合在一起.你知道为什么avg
删除了附加组吗?
@Evan Allen,我同意这通常很简单,因为您有一定数量的列可以作为枢轴。我认为您的查询可以简单得多,但是考虑将其更改为CASE WHEN bedrom = 0 THEN price END
,与CASE .... ELSE NULL END
相同,这样聚合函数就会忽略这些。我建议编辑,但队列已满【参考方案3】:
使用过滤器实现的另一种解决方案:
SELECT neighborhood,
avg(price) FILTER (WHERE bedrooms = 0) AS "0",
avg(price) FILTER (WHERE bedrooms = 1) AS "1",
avg(price) FILTER (WHERE bedrooms = 2) AS "2",
avg(price) FILTER (WHERE bedrooms = 3) AS "3"
FROM listings
GROUP BY neighborhood;
【讨论】:
以上是关于使用 PostgreSQL 创建数据透视表的主要内容,如果未能解决你的问题,请参考以下文章
使用 Redshift (PostgreSQL) 和计数的数据透视表