PostgreSQL 中的反透视表

Posted

技术标签:

【中文标题】PostgreSQL 中的反透视表【英文标题】:Unpivot table in PostgreSQL 【发布时间】:2020-10-08 17:48:16 【问题描述】:

作为 SUM(Case....End) 的结果,我有下表。

Account            Product_A            Product_B           Product_C
101                 1000                  2000                 3000
102                 2000                  1000                  0
103                 2000                  1000                  0
104                 2000                  1000                  2000

我想把它放回原来的桌子。像这样:

Account         Product               Qty
101               A                  1000
...               ..                 ....

我认为“Unpivot”可以在 MS SQL Server 中完成。但我只使用 PostgreSQL。 Postgresql 中可以返回/取消组合上表的 Unpivot 的等价物是什么? 谢谢

【问题讨论】:

【参考方案1】:

您可以使用带值子句的横向连接:

select t.account, u.product, u.qty
from the_table t
  cross join lateral ( 
     values ('A',product_a), ('B', product_b), ('C', product_c)
  ) as u(product, qty)
order by t.account;

Online example

【讨论】:

【参考方案2】:

我认为unnest 会帮助你:

SELECT Account,
       unnest(array['A', 'B', 'C']) AS Product,
       unnest(array[Product_A, Product_B, Product_C]) AS Qty
FROM test
ORDER BY Account;

FIDDLE

【讨论】:

【参考方案3】:

即使通过使用 JSON 函数将更多列(例如 Product_D)添加到表中,您也可以动态地取消透视这些列:

SELECT account, UPPER(SPLIT_PART((js).key, '_', 2)) AS Product, (js).value AS Qty 
  FROM( SELECT rj->>'account' AS Account, JSON_EACH_TEXT(rj) AS js
          FROM ( SELECT ROW_TO_JSON(t) AS rj FROM t) AS q1 ) AS q2
 WHERE (js).key != 'account';

Demo

同时根据为现有列名 (Product_A/B/C) 定义的模式拆分 Products 的列名,而无需明确指定每个字母。

【讨论】:

以上是关于PostgreSQL 中的反透视表的主要内容,如果未能解决你的问题,请参考以下文章

使用 PostgreSQL 创建数据透视表

Databricks/Spark SQL 中的反透视表

SQL Server 中的反透视表

postgresql中的数据透视表

动态数据透视,postgresql中的交叉表

如何运行从 postgresql 中的函数生成的查询