SQL(postgresql)查询年份提取和总和

时间:2010-11-05 10:20:55

标签: postgresql sql

我尝试在表上收集一些简单的统计信息,比如简化的结构如下:

  ID  |      CREATIONDATE        |    VALUE    |
------------------------------------------------
  1   | 2007-01-06 13:54:00.000  |      7      |
  2   | 2007-03-07 15:03:00.000  |      8      |
  3   | 2008-07-02 18:55:00.000  |      12     |
  4   | 2008-09-10 19:12:00.000  |      1      |
  5   | 2010-01-06 13:54:00.000  |      4      |
  6   | 2010-01-07 07:13:00.000  |      5      |

我想根据创建日期的年份对值进行求和,所以目前我执行以下操作:

select extract('year' from i.creationdate) as d1,
       sum(i.value)
  from items i
  group d1
  order by d1;

将输出

2007;15
2008;13
2010;9

有没有什么方法可以改进查询,让它自动为缺少的2009年输出0,即使表格中没有行在2009年有日期?

2007;15
2008;13
2009;0
2010;9

4 个答案:

答案 0 :(得分:3)

使用生成系列

中的左外连接
select year_list.year,
       coalesce(item_list.val,0)
 from (select generate_series(2007,2010) as year) AS year_list
       left outer join
      (select date_part('year',creationdate) item_year,sum(value) as val from i group by item_year) AS item_list 
      on item_year = year_list.year;     

为避免硬编码generate_series中的年份,请在年份部分替换select min()和max()。

答案 1 :(得分:3)

在JOIN中使用generate_series:

SELECT 
    generate_series as d1, 
    COALESCE(sum(i.value) , 0)
FROM 
    generate_series(2005, 2010) 
        LEFT JOIN items i ON generate_series = extract('year' from i.creationdate)
GROUP BY
    d1 
ORDER BY
    d1;

答案 2 :(得分:1)

我会在执行查询的软件中执行此操作,而不是在查询本身中执行此操作。

我已经通过在SQL中使用for循环来完成这些事情(例如在Oracle中)(毫无疑问在Postgres中有类似的东西)然而我得出的结论是错误的方法。与我简单地用应用程序的编程语言编写代码相比,解决方案更难维护。

SQL返回存在的数据,并对存在的数据进行操作,在这种情况下,没有相关年份的数据。这就是为什么尝试让SQL执行此操作不合适的原因。只需向SQL询问您拥有的数据,以及用您的编程语言为用户生成输出(例如HTML表),然后添加for循环以在第一年和最后一年之间迭代,如果没有结果则打印零

答案 3 :(得分:0)

一种简单(但不是很好)的方法是创建一个(临时)表,在一列中保存所有年份。然后,您只需将数据表加入新表。