【发布时间】:2019-09-23 12:14:36
【问题描述】:
我一直在探索 PostgreSQL 的 tablefunc extension module 中的 crosstab() 函数,作为生成数据透视表的一种方式。
这很棒,但似乎只适用于最基本的用例。它通常只支持三列输入:
- 一列保持不变的值,作为行标签
- 一列值被转置,成为新的列名
- 一列值成为其各自新数据透视列的值
基本上是这样的:
+------+----------+-------+
| 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 |
+------+--------+--------+----------+
但是更复杂的用例呢?如果你有:
- 您希望在输出中保持原样的多个输入列?
- 您希望将多个输入列转换为新列?
如下例:
+--------+-----------------+---------+--------+-------+------------------+
| 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 列有两个关联的列(即value 和confidence_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