Postgres 将长格式转换为宽格式

Postgres convert long to wide format

很抱歉,如果这个问题以前有人回答过,请随时指给我看,但我找不到一个基本的、干净的答案(我觉得应该是)一个相对基本的问题。

我想将 postgres table 从长格式转换为宽格式。

假设我有一个 table...

date value id
2022-01-01 100 1
2022-01-02 200 1
2022-01-03 300 1
2022-01-01 100 2
2022-01-02 200 2
2022-01-03 300 2
2022-01-01 100 3
2022-01-02 200 3
2022-01-03 300 3

我想将其输出为...

date id_1_value id_2_value id_3_value
2022-01-01 100 100 100
2022-01-02 200 200 200
2022-01-03 300 300 300

如果您要回答,我想非常清楚地将 ID 转换为列的方式需要是动态的。例如,如果我对具有 100 个我事先不知道的不同 ID 的 table 执行此操作,则解决方案应该能够优雅地处理这个问题。

您所描述的 PIVOT 为 table。虽然这可以在 SQL 中完成,但它很乏味且容易出错,并且需要 a priori 对结果列的了解。如果添加了数据值,则需要重写查询(即将 id 4 添加到 table)。下面是一个例子。

with test_data ( dt, val, id) as 
     (values (date '2022-01-01', 100, 1)
           , (date '2022-01-02', 200, 1)
           , (date '2022-01-03', 300, 1)
           , (date '2022-01-01', 100, 2)
           , (date '2022-01-02', 200, 2)
           , (date '2022-01-03', 300, 2)
           , (date '2022-01-01', 100, 3)
           , (date '2022-01-02', 200, 3)
           , (date '2022-01-03', 300, 3)
     )
-- your query begins here
select dt, max(id_1_value), max(id_2_value), max(id_3_value)
  from ( 
         select dt 
              , case when id = 1 then val else null end id_1_value
              , case when id = 2 then val else null end id_2_value
              , case when id = 3 then val else null end id_3_value
           from test_data
       ) sq 
 group by dt
 order by dt;
  

作为替代方案,您可能需要研究 crosstab 函数。

虽然 SQL 能够创建 PIVOT,但它并非为此而设计。这个还是最好留给你的application presentation manager;