【问题标题】:How to create a PostgreSQL pivot table that pivots multiple columns?如何创建一个透视多列的 PostgreSQL 透视表?
【发布时间】:2019-09-23 12:14:36
【问题描述】:

我一直在探索 PostgreSQL 的 tablefunc extension module 中的 crosstab() 函数,作为生成数据透视表的一种方式。

这很棒,但似乎只适用于最基本的用例。它通常只支持三列输入:

  1. 一列保持不变的值,作为行标签
  2. 一列值被转置,成为新的列名
  3. 一列值成为其各自新数据透视列的值

基本上是这样的:

+------+----------+-------+
| ITEM |  STATUS  | COUNT |
+------+----------+-------+
| foo  | active   |    12 |
| foo  | inactive |    17 |
| bar  | active   |    20 |
| bar  | inactive |     4 |
+------+----------+-------+

...并产生这个:

+------+--------+--------+----------+
| ITEM | STATUS | ACTIVE | INACTIVE |
+------+--------+--------+----------+
| foo  | active |     12 |       17 |
| bar  | active |     20 |        4 |
+------+--------+--------+----------+

但是更复杂的用例呢?如果你有:

  1. 您希望在输出中保持原样的多个输入列?
  2. 您希望将多个输入列转换为新列?

如下例:

+--------+-----------------+---------+--------+-------+------------------+
| SYSTEM |  MICROSERVICE   |  MONTH  | METRIC | VALUE | CONFIDENCE_LEVEL |
+--------+-----------------+---------+--------+-------+------------------+
| batch  | batch-processor | 2019-01 | uptime |    99 |                2 |
| batch  | batch-processor | 2019-01 | lag    |    20 |                1 |
| batch  | batch-processor | 2019-02 | uptime |    97 |                2 |
| batch  | batch-processor | 2019-02 | lag    |    35 |                2 |
+--------+-----------------+---------+--------+-------+------------------+

前三列应该为每一行保留原样(无分组或聚合)。并且metric 列有两个关联的列(即valueconfidence_level)来进行透视?

+--------+-----------------+---------+--------------+-------------------+-----------+----------------+
| SYSTEM |  MICROSERVICE   |  MONTH  | UPTIME_VALUE | UPTIME_CONFIDENCE | LAG_VALUE | LAG_CONFIDENCE |
+--------+-----------------+---------+--------------+-------------------+-----------+----------------+
| batch  | batch-processor | 2019-01 |           99 |                 2 |        20 |              1 |
| batch  | batch-processor | 2019-02 |           97 |                 2 |        35 |              2 |
+--------+-----------------+---------+--------------+-------------------+-----------+----------------+

我不确定这是否仍然符合“数据透视表”的严格定义。但是,crosstab() 或任何其他现成的 PostgreSQL 函数是否可能产生这样的结果?如果不是,那么如何使用自定义 PL/pgSQL 函数生成它?谢谢!

【问题讨论】:

  • SQL 不是为做这样的事情而设计的。这在您的前端代码中做得更好。或者可能将动态列聚合成单个 JSON 值,

标签: sql postgresql pivot-table crosstab


【解决方案1】:

您可以尝试使用条件聚合

select system,MICROSERVICE , MONTH,
max(case when METRIC='uptime' then VALUE end) as uptime_value,
max(case when METRIC='uptime' then CONFIDENCE_LEVEL end) as uptime_confidence,
max(case when METRIC='lag' then VALUE end) as lag_value,
max(case when METRIC='lag' then CONFIDENCE_LEVEL end) as lag_confidence
from tablename
group by system,MICROSERVICE , MONTH

【讨论】:

  • 太棒了,谢谢!我对“数据透视表”一词非常感兴趣(我不能 100% 确定这是当你有多个“数据透视表”时)。我应该退后一步,思考实现实际结果的方法,而不必拘泥于指向某种方法的术语。
【解决方案2】:

另一种方法(我使用过的)是将数据写入文件,使用单独的实用程序以所需格式交叉表,然后将结果导入新表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多