【问题标题】:Create a pivot table with PostgreSQL使用 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

【问题讨论】:

    标签: sql postgresql aggregate-functions crosstab


    【解决方案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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      • 2018-03-29
      相关资源
      最近更新 更多