2015-11-04 5 views
0

У меня есть схема, как показано ниже, и я хочу запустить запрос, где я получаю столбец на выходе для каждой строки таблицы points.Запрос PostgreSQL с созданными столбцами

Таким образом, для каждой строки 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, поскольку я использую их во многих функциях.

ответ

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 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;

+0

Это специфичные для данных, представленных. Я просто приводил некоторые примеры данных. Существуют тысячи строк «использования» и более дюжины «точек». Нужно быть динамичным. – Gargoyle

+0

@Gargoyle: проверьте обновленный запрос. –

+0

Ничего себе, это круто. Благодаря! – Gargoyle