【问题标题】:How to do Pivoting/crosstab in PostgreSQL with dynamic field如何在 PostgreSQL 中使用动态字段进行透视/交叉表
【发布时间】:2013-12-19 22:57:53
【问题描述】:

我是 PostgreSQL 新手。

id | customer_id | form_id | field_id | field_name | form_submission_id |    value     |
---+-------------+---------+----------+------------+--------------------+--------------+
 1 |           2 |       7 | c313     | Program    |                  1 | 2013         |            
 2 |           2 |       7 | c313     | Program    |                  2 | PIP          |            
 3 |           2 |       7 | c313     | Program    |                  3 | CIP          |            
 4 |           2 |       7 | c343     | Broker     |                  1 | broker test  |
 5 |           2 |       7 | c343     | Broker     |                  2 | broker test1 |            
 6 |           2 |       7 | c343     | Broker     |                  3 | broker test2 |            
 7 |           2 |       7 | c339     | Class      |                  1 | Class test   |             
 8 |           2 |       7 | c339     | Class      |                  2 | Class test1  |            
 9 |           2 |       7 | c339     | Class      |                  3 | Class test2  |    

我想要这样的记录

customer_id form_id Program      Broker        Class        form_submission_id 
  2          7        2013       broker test   Class test        1
  2          7        PIP        broker test1  Class test1       1
  2          7        CIP        broker test2  Class test3       1

field_name 值将是动态的,而不是固定值。

我已经尝试过了,但是遇到了类似“错误:返回和 sql 元组描述不兼容”的错误

select * from crosstab (
    'select Distinct customer_id ,form_id , field_name from form_submissions_reports '
    )
    as newtable (
     customer_id integer,form_id integer,field_id1 varchar,field_id2 varchar,field_id3 varchar
    ); 

但重要的是,字段名称是动态的。

【问题讨论】:

  • 我用谷歌搜索但没有得到答复
  • 是的,没错。相关的贡献是第一个结果,相关的 StackOverflow dup 紧随其后:stackoverflow.com/questions/3002499/postgresql-crosstab-query
  • 但它有固定的状态值。我没有 field_name 的固定值
  • 然后编辑您的问题并解释您尝试了什么以及为什么该问题中的内容不起作用。
  • 强烈建议您在数据库之外的应用程序中进行交叉制表。这样更快更容易

标签: postgresql pivot crosstab


【解决方案1】:

设置示例:

create table form_submissions_reports (id integer, customer_id integer, 
form_id integer, field_id text, field_name text, form_submission_id integer,
"value" text);


insert into form_submissions_reports
select 1 ,2 ,7 , 'c313', 'Program',1 , '2013' union all
select 2 ,2 ,7 , 'c313', 'Program',2 , 'PIP' union all
select 3 ,2 ,7 , 'c313', 'Program',3 , 'CIP' union all
select 4 ,2 ,7 , 'c343', 'Broker',1 , 'broker test' union all
select 5 ,2 ,7 , 'c343', 'Broker',2 , 'broker test1' union all
select 6 ,2 ,7 , 'c343', 'Broker',3 , 'broker test2' union all
select 7 ,2 ,7 , 'c339', 'Class',1 , 'Class test' union all
select 8 ,2 ,7 , 'c339', 'Class',2 , 'Class test1' union all
select 9 ,2 ,7 , 'c339', 'Class',3 , 'Class test2';

这是您尝试的固定列数的解决方案:

select * 
from crosstab (
'select Distinct form_submission_id , customer_id ,form_id , field_name, value 
from form_submissions_reports order by form_submission_id ', 
'select Distinct field_name from form_submissions_reports'
)as newtable (
              form_submission_id integer, customer_id integer,form_id integer,field_id 
              varchar,field_id2 varchar,field_id3 varchar
              ); 

就我的经验而言,关系数据库不是为列数及其类型不固定的类型构建的。所以你必须作弊。

这只是为了娱乐。我在这个完全“动态”的解决方案(灵活的列数、数据驱动的名称)中看不到任何生产价值:

1) 创建这两个函数:

CREATE OR REPLACE FUNCTION foo()
RETURNS text as
$BODY$
DECLARE
dynamic_columns text;
BEGIN

select array_to_string(array_agg(distinct  field_name||' text'), ', ') into dynamic_columns from form_submissions_reports;

return 'select * from crosstab (
        ''select Distinct form_submission_id , customer_id ,form_id , field_name, value from form_submissions_reports order by form_submission_id '', 
    ''select Distinct field_name from form_submissions_reports''
    )
    as newtable (
     form_submission_id integer, customer_id integer,form_id integer, '|| dynamic_columns ||'
    )';


END;
$BODY$
LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION bar()
RETURNS void as
$BODY$
DECLARE
dyn_crosstab text;
BEGIN

DROP VIEW IF EXISTS barview;

select foo() into dyn_crosstab;

execute 'create view barview as '||dyn_crosstab;

END;
$BODY$
LANGUAGE plpgsql;

2) 执行 bar() 函数。这将为您提供新版本的“barview”视图。之后,查询 barview。

select bar();
select * from barview;

3) 要测试它是否是动态的,请插入一个具有不同字段名称值的新行,然后重复 2):

INSERT INTO form_submissions_reports
(
  id,  customer_id,  form_id,  field_id,
  field_name,  form_submission_id,  value
)
VALUES(  10,  2,  7,  'd',  'NEWFIELD',  4,
  'newfield test');

select bar();
select * from barview;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多