带有生成列的 PostgreSQL 查询
PostgreSQL query with generated columns
我有一个如下所示的模式,我想 运行 一个查询,在该查询中我在输出中为 points
table 的每一行获取一列。
因此,对于每个 usage
行,我想将使用量的 amount
乘以引用的 points_id
的 amount
,然后将其相加并分组由人。因此,对于示例数据,我希望输出如下所示:
Name | foo | bar | baz
-------|------|------|------
Scott | 10.0 | 24.0 | 0.0
Sam | 0.0 | 0.0 | 46.2
这是 schema/data:
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
table 中有数千行,points
table 中可能有十几行。这里的真正意图是我不想对所有 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';
函数使用临时 table 来存储动态列数据。
通过以下方式调用函数获取数据:
select * from sp_test(); select * from temp_data;
我有一个如下所示的模式,我想 运行 一个查询,在该查询中我在输出中为 points
table 的每一行获取一列。
因此,对于每个 usage
行,我想将使用量的 amount
乘以引用的 points_id
的 amount
,然后将其相加并分组由人。因此,对于示例数据,我希望输出如下所示:
Name | foo | bar | baz
-------|------|------|------
Scott | 10.0 | 24.0 | 0.0
Sam | 0.0 | 0.0 | 46.2
这是 schema/data:
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
table 中有数千行,points
table 中可能有十几行。这里的真正意图是我不想对所有 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';
函数使用临时 table 来存储动态列数据。
通过以下方式调用函数获取数据:
select * from sp_test(); select * from temp_data;