Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在postgres中创建按年份求和的表_Sql_Postgresql - Fatal编程技术网

Sql 如何在postgres中创建按年份求和的表

Sql 如何在postgres中创建按年份求和的表,sql,postgresql,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

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

首先,将销售总额的结果存储为t1

select product, year, sum(sales) as sales
  from table
  group by 1,2
  order by 1,2
然后使用交叉表()


有几种方法可以做到这一点。交叉表可能是最简单的,但它需要安装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

我发现在创建具有可变列数的交叉表查询时有几个问题。常规查询是不可能的,但可以使用

让我们创建函数

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)

您尝试过什么?您必须使用交叉表功能。@Roy它可以通过其他方式完成,并且交叉表功能是tablefunc扩展的一部分,必须安装。编辑应该是
然后是sales else 0 end
而不是
然后是1 else 0 end
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)