用于年份提取和求和的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;