如何使用postgres中的年份总结值创建表

时间:2016-02-17 01:06:07

标签: sql postgresql

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

4 个答案:

答案 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

SQL Fiddle