postgres数据库格式为:
year product sales account
2013 bread 10 001
2013 bread 5 002
2013 peanut 5 001
2013 jam 4 001
2013 jam 5 002
2014 bread 12 001
2014 bread 6 002
2014 peanut 6 001
2014 jam 5 001
2014 jam 3 002
所需的输出是按年份创建一个表,其中总计产品总和。
product 2013 2014
bread 15 18
peanut 5 6
jam 9 8
答案 0 :(得分:1)
Select
Product ,
Sum (case when year =2013 then 1 else 0 end) 2013,
Sum (case when year =2014 then 1 else 0 end) 2014
From your table
Group by
Product;
答案 1 :(得分:1)
首先将总销售额的结果存储为t1
select product, year, sum(sales) as sales
from table
group by 1,2
order by 1,2
然后你使用交叉表()
SELECT *
FROM crosstab(
'SELECT product, year, sales
FROM t1
ORDER BY 1,2')
AS foo("product" text, "2013" int, "2014" int);
答案 2 :(得分:1)
我看到有几个关于创建具有可变列数的交叉表查询的问题。常规查询是不可能的,但可以使用refcursors完成。
让我们创建
的功能1)构造查询,如:
select
name_field,
sum(value_field) filter (where column_field = c1) as col_1,
sum(value_field) filter (where column_field = c2) as col_2,
...
from
table
group by
name_field
其中c1,c2,...是我们列的常量
和2)返回此查询的游标:
create or replace function ct(
in p_sql text, -- Data providing query
in p_name_field varchar, -- Field with titles for rows
in p_column_field varchar, -- Field with titles for columns
in p_value_field varchar, -- Field with numeric data
p_cursor refcursor) returns refcursor as $$
declare
q text;
cols varchar[];
c varchar;
begin
-- Collect column names
execute 'select array_agg(distinct ' || p_column_field || '::varchar) from (' || p_sql || ') t' into cols;
-- Build query
q := 'select ' || p_name_field;
for c in (select unnest(cols)) loop
q := q || ', sum(' || p_value_field || ') filter (where ' || p_column_field || '::varchar = ' || quote_literal(c::text) || ') as col_' || c;
end loop;
q := q || ' from (' || p_sql || ') t group by ' || p_name_field || ' order by ' || p_name_field;
open p_cursor for execute q;
return p_cursor;
end; $$ language plpgsql;
多数民众赞成。现在我们可以将此函数用于OP的数据,如:
begin;
select ct('select * from sales', 'product', 'year', 'sales', 'ct_cur');
fetch all in ct_cur;
-- Yet another usage example:
select ct('select * from sales', 'product, account', 'year', 'sales', 'ct_cur_acc');
fetch all in ct_cur_acc;
-- And another one:
select ct('select * from sales', 'account, year', 'product', 'sales', 'ct_cur_prod');
fetch all in ct_cur_prod;
commit;
结果是:
product | col_2013 | col_2014
---------+----------+----------
bread | 15 | 18
jam | 9 | 8
peanut | 5 | 6
(3 rows)
product | account | col_2013 | col_2014
---------+---------+----------+----------
bread | 001 | 10 | 12
bread | 002 | 5 | 6
jam | 001 | 4 | 5
jam | 002 | 5 | 3
peanut | 001 | 5 | 6
(5 rows)
account | year | col_bread | col_jam | col_peanut
---------+------+-----------+---------+------------
001 | 2013 | 10 | 4 | 5
001 | 2014 | 12 | 5 | 6
002 | 2013 | 5 | 5 |
002 | 2014 | 6 | 3 |
(4 rows)
答案 3 :(得分:0)
有几种方法可以做到这一点。交叉表可能是最简单的,但它需要安装tablefunc扩展,您可能没有超级用户权限。
另一种方法是使用子查询,这使得添加新的2年简单的复制/粘贴/更新:
WITH
products as (
select product from sales group by product
),
sums AS (
select product, sum(sales) total_sales, year
from sales
group by product, year
)
SELECT
products.product,
"2013".total_sales as "2013",
"2014".total_sales as "2014"
FROM products
LEFT JOIN sums "2013" ON(products.product="2013".product and "2013".year=2013)
LEFT JOIN sums "2014" ON(products.product="2014".product and "2014".year=2014)
ORDER BY product