如何在 PostgreSQL 中旋转

Ale*_*eps 5 postgresql pivot

表中有以下数据:

ID     Category   Value
1234   Cat01      V001
1234   Cat02      V002
1234   Cat03      V003
1234   Cat03      V004
1234   Cat03      V005
Run Code Online (Sandbox Code Playgroud)

我想要以下输出:

ID     Cat01  Cat02   Cat03
1234   V001   V002    V003
1234   V001   V002    V004
1234   V001   V002    V005
Run Code Online (Sandbox Code Playgroud)

我想要实现的输出是一种数据透视表,其中我将所有值垂直放置在一个表中,并且我希望将这些值水平放置,并将类别作为列。但是有些类别具有多个值,在这种情况下,我需要重复所有其他类别的值并为每个重复值创建一行

如何在 PostgreSQL 中完成?

Erw*_*ter 5

这是一个棘手的问题。对于每个row_name ,每个类别crosstab()需要一个(或没有)

我们可以像这样解决这个限制:

SELECT id
     , COALESCE(cat01, max(cat01) OVER w)
     , COALESCE(cat02, max(cat02) OVER w)
     , COALESCE(cat03, max(cat03) OVER w)
FROM   crosstab(
   'SELECT id::text || row_number() OVER (PARTITION BY id, category ORDER BY value) * -1 AS ext_id
         , id, category, value
    FROM   tbl
    ORDER  BY ext_id, category, value'

   ,$$VALUES ('Cat01'::text), ('Cat02'), ('Cat03')$$
   ) AS ct (xid text, id int, cat01 text, cat02 text, cat03 text)
WINDOW w AS (PARTITION BY id);
Run Code Online (Sandbox Code Playgroud)

返回您想要的结果。

如何?

  1. 添加一个扩展的 id: ext_idfrom the existingid和一个行号,为相同的类别的每个值添加一个行号id。通过这种方式,我们确保每个id输入的行数与最常见类别的值一样多。我们得到一个这样的派生表来构建我们crosstab()的:

    SELECT id
         , COALESCE(cat01, max(cat01) OVER w)
         , COALESCE(cat02, max(cat02) OVER w)
         , COALESCE(cat03, max(cat03) OVER w)
    FROM   crosstab(
       'SELECT id::text || row_number() OVER (PARTITION BY id, category ORDER BY value) * -1 AS ext_id
             , id, category, value
        FROM   tbl
        ORDER  BY ext_id, category, value'
    
       ,$$VALUES ('Cat01'::text), ('Cat02'), ('Cat03')$$
       ) AS ct (xid text, id int, cat01 text, cat02 text, cat03 text)
    WINDOW w AS (PARTITION BY id);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 现在我们可以将它提供给crosstab()使用安全的 2 参数形式来丢失属性。如果您对此不熟悉,请先阅读基础知识:

  1. 你的问题留下了解释的空间。我的解决方案首先将每个类别的最低值配对,然后继续填充以下行,直到没有值为止。(我们可以以任何其他方式组合每个类别的多个值,它尚未定义。)如果一个类别缺少给定的值id,其余的将用 NULL 值填充。

  2. 在最后一步中,我将这些 NULL 值替换为每个categoryper的最大值id

     COALESCE(cat01, max(cat01) OVER (PARTITION BY id, category))
    
    Run Code Online (Sandbox Code Playgroud)

    这实际上等同于:

     max(cat01) OVER (PARTITION BY id, category)
    
    Run Code Online (Sandbox Code Playgroud)

    如果我们仅在值为 NULL 时默认使用窗口函数,我希望让它稍微快一点。


Raz*_*ici -2

您看到的是交叉表。假设您的表名为“Fact_Table”,请写入:

select * from crosstab('从 Fact_Table 中选择 id、类别、值')

如果您寻找其他变体,另请参阅http://www.postgresql.org/docs/9.5/static/tablefunc.html 。