假设我需要一个查询来按月查看销售结果,并且我希望结果集包含每个月的结果,无论该月是否有任何销售。
假设我的表“sales”有“sales_date”和“sales_amount”列,我希望结果集如下所示:
一月 100.00
二月 240.00
三月 0.00
四月 430.00
因此,如果我想按月对值求和并且没有任何 Mar 的记录,我仍然希望看到 Mar 的结果为 0。我该怎么做?
在 postgres 中获取系列的常用方法是使用generate_series。此函数生成一系列整数或时间戳 - 您可以使用其中任何一个,但假设您的“日期”确实是timestamptz
,如果您使用的是 8.4 或更高版本,则可以使用以下方法:
试验台:
create table sales(sales_date timestamptz, sales_amount numeric);
insert into sales(sales_date, sales_amount) values('2011-01-15 12:00', 100);
insert into sales(sales_date, sales_amount) values('2011-02-15 12:00', 240);
insert into sales(sales_date, sales_amount) values('2011-04-15 12:00', 400);
insert into sales(sales_date, sales_amount) values('2011-04-16 12:00', 30);
Run Code Online (Sandbox Code Playgroud)
询问:
with w as ( select month, sum(sales_amount) as total
from (select date_trunc('month',sales_date) as month, sales_amount from sales) z
group by month )
select to_char(month, 'fmMon') as month, coalesce(total, 0) as total
from (select generate_series(min(month), max(month), '1 month'::interval) as month from w) m
left outer join w using(month);
Run Code Online (Sandbox Code Playgroud)
结果:
month | total
-------+-------
Jan | 100
Feb | 240
Mar | 0
Apr | 430
Run Code Online (Sandbox Code Playgroud)
--edit:关于查询的一些额外细节:
按月生成销售摘要(但如果没有销售,则不存在月份):
with w as ( select month, sum(sales_amount) as total
from ( select date_trunc('month',sales_date) as month, sales_amount
from sales ) z
group by month )
Run Code Online (Sandbox Code Playgroud)
也可以写成:
with w as ( select date_trunc('month',sales_date) as month, sum(sales_amount) as total
from sales
group by date_trunc('month',sales_date) )
Run Code Online (Sandbox Code Playgroud)产生从最小值到最大值的连续的月份系列(没有销售):
select generate_series(min(month), max(month), '1 month'::interval) as month from w
Run Code Online (Sandbox Code Playgroud)外部将完整的系列加入到按月的销售汇总中,以生成带有销售额的完整系列(null
如果没有销售额,则为销售额):
left outer join w using(month)
Run Code Online (Sandbox Code Playgroud)对于null
销售月份,将 更改null
为 a 0
:
coalesce(total, 0)
Run Code Online (Sandbox Code Playgroud)