PostgreSQL查询生成的列

时间:2015-11-04 20:49:22

标签: sql postgresql pivot crosstab

我有一个如下所示的模式,我想运行一个查询,我在输出中为points表的每一行输入一列。

因此,对于每个usage行,我希望将amount的使用时间与引用的amount的{​​{1}}相乘,然后将其加总并按人分组。因此,对于示例数据,我希望输出看起来像这样:

points_id

这里是架构/数据:

 Name  | foo  | bar  | baz  
-------|------|------|------
 Scott | 10.0 | 24.0 | 0.0  
 Sam   | 0.0  | 0.0  | 46.2   

我正在使用PostgreSQL 9.2.8

数据只是样本。真实CREATE TABLE points ( ident int primary key NOT NULL, abbrev VARCHAR NOT NULL, amount real NOT NULL ); CREATE TABLE usage ( ident int primary key NOT NULL, name VARCHAR NOT NULL, points_id integer references points (ident), amount real ); INSERT INTO points (ident, abbrev, amount) VALUES (1, 'foo', 1.0), (2, 'bar', 2.0), (3, 'baz', 3.0); INSERT INTO usage (ident, name, points_id, amount) VALUES (1, 'Scott', 1, 10), (2, 'Scott', 2, 12), (3, 'Sam', 3, 3.4), (4, 'Sam', 3, 12); 表中有数千行,usage表中可能有十几行。这里的真正意图是我不想对所有points求和进行硬编码,因为我在许多函数中使用它们。

1 个答案:

答案 0 :(得分:0)

select 
t1.name,
sum(case when t2.abbrev='foo' then t1.amount*t2.amount else 0 end) as foo,
sum(case when t2.abbrev='bar' then t1.amount*t2.amount else 0 end) as bar,
sum(case when t2.abbrev='baz' then t1.amount*t2.amount else 0 end) as baz
from usage t1 inner join points t2 on t1.points_id=t2.ident
group by t1.name;

SQL小提琴示例:http://sqlfiddle.com/#!15/cc84a/6;

对动态案例使用以下PostgreSQL函数:

create or replace function sp_test()
returns void as
$$

declare cases character varying;
declare sql_statement text;
begin

select string_agg(concat('sum(case when t2.abbrev=','''',abbrev,'''',' then t1.amount*t2.amount else 0 end) as ', abbrev),',') into cases from points;

drop table if exists temp_data;

sql_statement=concat('create temporary table temp_data as select 
t1.name,',cases ,' 
from usage t1 inner join points t2 on t1.points_id=t2.ident
group by t1.name ');

execute sql_statement;

end;
$$
language 'plpgsql';

函数使用临时表来存储动态列数据。

以下列方式调用函数来获取数据:

select * from sp_test(); select * from temp_data;