Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/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(postgresql)查询_Postgresql_Sql - Fatal编程技术网

用于年份提取和求和的SQL(postgresql)查询

用于年份提取和求和的SQL(postgresql)查询,postgresql,sql,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

我试图在一张表上收集一些简单的统计数据,假设简化结构如下:

  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;
我想根据创建日期的年份对值求和,因此目前我执行以下操作:

  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

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

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

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

我做过这样的事情,例如在Oracle中使用SQL中的for循环毫无疑问在Postgres中也有类似的事情,但我得出的结论是,这是错误的方法。与我简单地用应用程序的编程语言编写代码相比,该解决方案更难维护

SQL返回已存在的数据,并对已存在的数据进行操作,在这种情况下,没有相关年份的数据。这就是为什么不适合尝试使用SQL来实现这一点。只要向SQL查询您确实拥有的数据,当您用编程语言为用户生成输出时,例如HTML表,然后添加for循环,在第一年和最后一年之间进行迭代,如果没有结果,则打印零。

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

我做过这样的事情,例如在Oracle中使用SQL中的for循环毫无疑问在Postgres中也有类似的事情,但我得出的结论是,这是错误的方法。与我简单地用应用程序的编程语言编写代码相比,该解决方案更难维护


SQL返回已存在的数据,并对已存在的数据进行操作,在这种情况下,没有相关年份的数据。这就是为什么不适合尝试使用SQL来实现这一点。只需向SQL查询您确实拥有的数据,当您用编程语言为用户生成输出时,例如HTML表,然后添加for循环,在第一年和最后一年之间进行迭代,如果没有结果,则打印零。

使用generate系列中的左外联接

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_系列中的年份进行硬编码,请在年份部分选择最小值和最大值。

使用generate系列中的左外联接

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_系列中的年份,请在年份部分选择最小值和最大值。

在联接中使用generate_系列:

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;

在联接中使用生成_系列:

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;