动态数据透视,postgresql中的交叉表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态数据透视,postgresql中的交叉表相关的知识,希望对你有一定的参考价值。

以下是动态转动的功能:

create extension tablefunc;

-- tablename: name of source table you want to pivot

-- rowc: the name of the column in source table you want to be the rows

-- colc: the name of the column in source table you want to be the columns

-- cellc: an aggregate expression determining how the cell values will be created

-- celldatatype: desired data type for the cells

----------

create or replace function pivotcode(tablename varchar, rowc varchar, rowd varchar,colc varchar, cellc varchar, celldatatype varchar) returns varchar language plpgsql as $$

declare

    dynsql1 varchar;
    dynsql2 varchar;
    columnlist varchar;
begin
    -- 1. retrieve list of column names.

    dynsql1 = 'select string_agg(distinct ''_''||'||colc||'||'' '||celldatatype||''','','' order by ''_''||'||colc||'||'' '||celldatatype||''') from '||tablename||';';
    execute dynsql1 into columnlist;

 -- 2. set up the crosstab query

    dynsql2 = 'select * from crosstab (''select '||rowc||','||rowd||','||colc||','||cellc||' from '||tablename||' group by 1,2,3 order by 1,2,3'',''select distinct '||colc||' from '||tablename||' order by 1'')as newtable ('||rowc||' varchar,'||rowd||' varchar,'||columnlist||' );';
    return dynsql2;end$$


-- toy example to show how it works

 create table table_to_pivot (dates varchar,article varchar,promo varchar);


insert into table_to_pivot values ('11-02-2013','abc',11);

insert into table_to_pivot values ('11-02-2013','def',12);

insert into table_to_pivot values ('12-02-2013','abc',11);

insert into table_to_pivot values ('12-02-2013','def',11);

insert into table_to_pivot values ('13-02-2013','ghi',22);

insert into table_to_pivot values ('14-02-2013','def',12);

insert into table_to_pivot values ('15-02-2013','abc',22);

insert into table_to_pivot values ('16-02-2013','ghi',32);

insert into table_to_pivot values ('17-02-2013','acb',12);

      dates    |promo   |article|  
     2013-02-11    abc     11           
     2013-02-11    def     12   
     2013-02-12    abc     11         
     2013-02-12    def     11     
     2013-02-13    ghi     22        
     2013-02-14    def     12   
     2013-02-15    abc     22  
     2013-02-16    ghi     32  
     2013-02-17    acb     12       

select pivotcode('table_to_pivot','dates','article','promo','max(1)','integer');

select * from crosstab (
    'select dates,article,promo,max(1) from table_to_pivot group by 1,2,3 order by 1,2,3',
    'select distinct promo from table_to_pivot order by 1'
    )
    as newtable (
    dates date,article varchar,_abc integer,_def integer,_ghi integer,_acb integer
    );

输出表是:

dates      |article  |abc | def| ghi | acd
2013-02-11  11         1   null    1   null  
2013-02-12  11         1   null    1   null
2013-02-13  22        null null  null   1
2013-02-14  12        null null  null   1
2013-02-15  22         1   null  null  null
2013-02-16  32        null null  null   1
2013-02-17  12        null   1   null  null

有2个错误:

  • 列名称及其值不准确(例如'abc'的值在列'ghi'中)
  • 在不同的促销上的wheareas同一日期与不同的文章,我得到的输出只是第一次约会及其文章
  • 结果表应该是 dates |article |abc | def | ghi | acd 2013-02-11 11 1 null null null 2013-02-11 12 null 1 null null 2013-02-12 11 1 null null null 2013-02-12 11 null 1 null null 2013-02-13 22 null null 1 null 2013-02-14 12 null 1 null null 2013-02-15 22 1 null null null 2013-02-16 32 null null 1 null 2013-02-17 12 null null null 1
答案

您可以使用text ARRAY[]来获取应该分组的数据。最好使用double-dolar quotes而不是single quotes。试试这个查询;

select  newtable.datas[1] as dates,newtable.datas[2] as 
        article,newtable._abc,newtable._def,newtable._ghi,newtable._acb
from crosstab (
     $$select Array[dates,promo,article],article,max(1) 
       from table_to_pivot group by 1,2 order by 1,2$$,
     $$select article from table_to_pivot
       group by 1
       order by (case
             when article = 'abc' then 1
             when article = 'def' then 2
             when article = 'ghi' then 3
             else 4
             end)$$
      )
      as newtable (
      datas text[],_abc integer,_def integer,_ghi integer,_acb integer
      ) ;

以上是关于动态数据透视,postgresql中的交叉表的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 交叉表/数据透视问题

使用 PostgreSQL 创建数据透视表

数据分析处理——透析表和交叉表

动态 SQL 使用多列交叉应用来反透视数据

具有动态列名和多个输入列的 PostgreSQL 交叉表

postgresql中的数据透视表