【问题标题】:crosstab with 2 (or more) row names具有 2 个(或更多)行名称的交叉表
【发布时间】:2014-02-04 05:41:49
【问题描述】:

我正在尝试转置具有 2 个行名的表。
Postgres 文档提到 crosstab() 函数只能处理 1 行名称,但我有 2 行名称,例如名字和姓氏。

我的初始表是:

fn |  ln |  file_type |attribute
--------------------------------
A  |  1  |  cat1     |abc
A  |  2  |  cat1     |gth
A  |  1  |  cat2     |fgh
B  |  1  |  cat2     |gth

我希望我的最终表格包含 2 个初始行和文件类型转置

 fn |  ln |  cat1 | cat2
--------------------------------
 A  |   1 |  abc  | fgh
 A  |   2 |  gth  | 
 B  |   1 |       | gth

我在 functools 中找不到我需要的东西...

版本是 Postgres 9.3

【问题讨论】:

    标签: sql postgresql pivot-table crosstab transpose


    【解决方案1】:

    使用附加模块 tablefunc 中的crosstab()

    这里的具体困难是“行名”由两列组成。我出于查询的目的进行连接,并且不在末尾显示连接的列。
    假设fnlnNOT NULL。未经测试:

    SELECT fn, ln, cat1, cat2
    FROM crosstab(
           'SELECT fn || ln AS row_name, fn, ln, file_type, attribute
            FROM   t
            ORDER  BY fn, ln, file_type'
    
          ,$$VALUES ('cat1'::text), ('cat2')$$)
    AS t (row_name text, fn text, ln int, cat1 text, cat2 text);
    

    另一种选择是添加一个代理“行名”,其窗口函数类似于dense_rank(),并将定义的两列视为“额外列”。示例:

    基础知识:

    【讨论】:

    • 如果 all row_name 的额外列“预期相同”,这是一个很好的解决方案。有没有办法使用交叉表进行多级透视/分层透视?
    • 哈!在您的other answers 之一中找到了解决方案。除了我使用 dense_rank() 在我想要的分组上生成代理键,然后将其用作 row_name 到交叉表。
    【解决方案2】:

    这是我在数据库中进行透视时的典型后备方法:

    select fn,
           ln,
           max(case file_type when 'cat1' then attribute end),
           max(case file_type when 'cat2' then attribute end)
    from testdata
    group by fn,
             ln
    ;
    

    如果您删除聚合,那么您可以看到 case 表达式仅对于具有指定类别的类的行将是非空的(对于该类,所有其他行应该为空在该类别中,尽管如果不是这种情况,这将默默地选择一个)。 max 只是选择非空值的一种方法(您可以使用 min,或任何其他可以从集合中选择单个非空值的聚合)。

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 2021-08-01
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多