如何创建可旋转多个列的PostgreSQL数据透视表?

时间:2019-09-23 12:14:36

标签: sql postgresql pivot-table crosstab

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

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

  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函数生成它?谢谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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