我有一个如下所示的架构,并且我想运行一个查询,在该查询中我在points表的每一行的输出中都有一列。
points
因此,对于每一usage行,我想将引用amount的用法乘以,然后将其加起来并按人分组。因此,对于示例数据,我希望输出如下所示:amount``points_id
usage
amount
amount``points_id
Name | foo | bar | baz -------|------|------|------ Scott | 10.0 | 24.0 | 0.0 Sam | 0.0 | 0.0 | 46.2
这是模式/数据:
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);
我正在使用PostgreSQL 9.2.8
数据仅是示例。实际usage表中有数千行,而表中可能有十几行points。真正的目的是我不想对所有points求和进行硬编码,因为我在许多函数中都使用了它们。
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 Fiddle示例: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;