【问题标题】:Pivot / crosstab with more than one value column具有多个值列的数据透视表/交叉表
【发布时间】:2015-07-13 21:54:16
【问题描述】:

我有一个生成以下结果集的视图:

CREATE TABLE foo
AS
  SELECT client_id, asset_type, current_value, future_value
  FROM ( VALUES
    ( 1, 0, 10 , 20 ),
    ( 1, 1, 5  , 10 ),
    ( 1, 2, 7  , 15 ),
    ( 2, 1, 0  , 2 ),
    ( 2, 2, 150, 300 )
  ) AS t(client_id, asset_type, current_value, future_value);

我需要把它变成这样:

client_id    a0_cur_val   a0_fut_val  a1_cur_val  a1_fut_val  ...
1            10           20          5           10          
2            NULL         NULL        0           2           

如果我只使用current_value 列,使用交叉表,我知道该怎么做。如何使用current_valuefuture_value 在目标结果集中生成新列?如果我只是将future_value 列添加到crosstab(text) 查询中,它会抱怨“无效的源数据SQL 语句”。

我使用的是 PostgreSQL 9.3.6。

【问题讨论】:

  • 如果有人认为有帮助,我可以只使用一列发布交叉表查询。
  • 发布到目前为止您已经/尝试过的内容总是有帮助的。

标签: sql postgresql crosstab


【解决方案1】:

一种方法是使用复合类型:

CREATE TYPE i2 AS (a int, b int);

或者,对于临时使用(在会话期间注册类型):

CREATE TEMP TABLE i2 (a int, b int);

然后运行你所知道的交叉表并分解复合类型:

SELECT client_id
     , (a0).a AS a0_cur_val, (a0).b AS a0_fut_val
     , (a1).a AS a1_cur_val, (a1).b AS a1_fut_val
     , (a2).a AS a2_cur_val, (a2).b AS a2_fut_val
FROM   crosstab(
       'SELECT client_id, asset_type, (current_value, future_value)::i2
        FROM   foo
        ORDER  BY 1,2'

      ,'SELECT * FROM generate_series(0,2)'
   ) AS ct (client_id int, a0 i2, a1 i2, a2 i2);

所有括号都是必需的

crosstab() 的基础知识:

【讨论】:

  • 我认为 ARRAY 甚至 POINT 在这里更有意义,但答案很酷。
  • @EvanCarroll:是的,当所有列碰巧具有相同的数据类型或者可以转换为text 时。以上适用于任何类型的组合。
【解决方案2】:

另一种选择是从两个交叉表查询中构造一个连接,您可以使用它来独立恢复两组值中的任何一个...含义:

select coalesce(cur.client_id, fut.client_id) client_id
, c0, f0, c1, f1, c2, f2
from
(select client_id, c0, c1, c2
from crosstab 
    ('select client_id, asset_type, current_value
    from foo
    order by client_id, asset_type')
as sal1 (client_id int4, c0 int4 , c1 int4 , c2 int4)) cur
full outer join 
(select client_id, f0, f1, f2
from crosstab 
    ('select client_id, asset_type, future_value
    from foo
    order by client_id, asset_type')
as sal1 (client_id int4, f0 int4 , f1 int4 , f2 int4)) fut
on fut.client_id = cur.client_id

含义...在两个不同的交叉表查询中获取 current_value 和 future_value,然后将它们连接起来以在连接查询中得到结果

  • 我对 client_id 使用了完全外连接和合并,以防任何客户端不能出现在包含当前值的第一个查询中,如果我们知道 current_value 总是存在,我们可以使用左连接,如果两者都存在,需要当前值和未来值,然后内部连接就可以了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多