创建 GroupBy 查询以在没有结果匹配时包含结果

dmi*_*onj 4 postgresql query

假设我需要一个查询来按月查看销售结果,并且我希望结果集包含每个月的结果,无论该月是否有任何销售。

假设我的表“sales”有“sales_date”和“sales_amount”列,我希望结果集如下所示:

一月 100.00
二月 240.00
三月 0.00
四月 430.00

因此,如果我想按月对值求和并且没有任何 Mar 的记录,我仍然希望看到 Mar 的结果为 0。我该怎么做?

Jac*_*las 8

在 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)