PostgreSQL中的转置表

时间:2017-09-18 14:16:51

标签: sql postgresql pivot

我在PostgreSQL中有一个表格,如:

org_name | month_1 | month_2 | ... | month_12
---------------------------------------------
org1     |  20     |   30    | ... |  15
org2     |  34     |   27    | ... |  49

我需要将其转置为:

month  |  org1 | org2 
----------------------
   1   |   20  | 34
   2   |   30  | 27
..     |   ..  | ..
  12   |   15  | 49

我在stackoverflow上找到了下一个解决方案:

SELECT
    *
FROM 
    (select org_name, monthes, value
    from my_table
    unpivot
    (
        value
        for monthes in (month_2, month_3, month_4, month_5, month_6, month_7, month_8, month_9, month_10, month_11, month_12)
    ) unpiv
    ) src
    pivot
    ( 
        sum(value)
        for org_name in ('org1', 'org2')
    ) piv

但是对于'而言,它并没有处理语法错误。我哪里错了?

2 个答案:

答案 0 :(得分:0)

我还没有能够让你的方法工作;但这个多步联盟似乎。

With myTable (org_name, month_1, Month_2, month_3, Month_12) as (
    Select 'org1',20,30,40,15 union all
    Select 'org2',34,27,45,49),

cte  (Mo,Org1,org2) as(select unnest(ARRAY[1,2,3,12]) AS Mo
     , case when org_name='org1' then unnest(ARRAY[month_1, Month_2,month_3,Month_12]) end as Org1
     , case when org_name='org2' then unnest(ARRAY[month_1, Month_2,month_3,Month_12]) end as Org2
     from mytable)

     Select mo,sum(org1) org1, sum(org2) org2
     From cte
     group by mo

也许你会发现更明显的问题:

{{1}}

答案 1 :(得分:0)

实际上,你需要像 plus pivot这样的东西。

1。 将每行分解行以获得单个条目(“unpivot”):

SELECT mon, org_name, val
FROM   tbl, LATERAL (
   VALUES
      (1, month_1)
    , (2, month_2)
    -- ... more
    , (12, month_12)
   ) x(mon, val)
ORDER  BY 1, 2;

如果有更多组织,您必须添加WHERE子句来选择相关的组:

WHERE  org_name IN ('org1', 'org2')

2。 ,将其提供给crosstab()以获得您想要的结果:

SELECT *
FROM   crosstab($$
      SELECT mon, org_name, val
      FROM   tbl, LATERAL (
         VALUES
            (1, month_1)
          , (2, month_2)
          -- ... more
          , (12, month_12)
         ) x(mon, val)
      WHERE  org_name IN ('org1', 'org2')
      ORDER  BY 1, 2$$)
   AS ct (month int, org1 int, org2 int);

VOILÀ。

crosstab()功能由附加模块 tablefunc 提供,因此必须安装。
详细说明和链接:

自动化:

这是为任何组织列表和任何月份列表构建SQL语句的基本功能:

CREATE OR REPLACE FUNCTION f_unpivot_colums(_orgs text[], _months int[])
  RETURNS text AS
$func$
SELECT 'SELECT *
FROM   crosstab($$
   SELECT x.mon, t.org_name, x.val
   FROM   tbl t, LATERAL (
      VALUES '
       || string_agg(format('(%s, t.%I)', m, 'month_' || m), ', ')
       || ') x(mon, val)
   WHERE  t.org_name = ANY (' || quote_literal(_orgs) || ')
   ORDER  BY 1, 2$$)
AS ct (month int, org1 int, org2 int)'
FROM   unnest(_months) m
$func$  LANGUAGE sql;

您也可以动态提取组织或月份列表......

呼叫:

SELECT f_unpivot_colums('{org1, org2}', '{1,2,12}')

生成上述语句 - 您可以依次执行。