SQL 查询过去 365 天的报告

SQL query for last 365 days report

我有一份报告 table,结构如下:

我想要一个 SQL 查询,以根据以下条件获取最近 365 天的报告:

  1. 如果重复相同的日期,则将日期分组。
  2. 最近 365 天报告不可用的天数,我需要将这些天数添加到结果行中,其中 0 作为成功和失败的收件人。

我试着按报告日期分组

SELECT report_date, SUM(success_recipient) as success_recipient, SUM(failed_recipient) as failed_recipient FROM reports GROUP BY report_date;

得到满足第一个条件的分组结果

现在我需要将过去 365 天的剩余天数附加到此结果中,其中 0 作为成功和失败的收件人。

预期结果:

等等..

MYSQL 版本:5.6

实现此目的的一种方法是使用“递归”生成输出中需要的所有日期,然后外连接到查询的其余部分。注意:我使用您描述中的数字 356,但使用日期差异似乎更合适,因为这种方法没有考虑闰年。如果没有数据,使用下面的查询将得到 NULL 值。如果您需要值 0,您可以使用 coalesce(sum(...), 0).

with recursive
dates as (
  select curdate()-356 dt
  union all
  select dt+1 from dates
  where dt < curdate()
)
select 
  dt report_date,
  sum(success_recipient) success_recipient, 
  sum(failed_recipient) failed_recipient
from dates
left join reports on report_date = dt
group by report_date;

从上面的评论和答案,我可以写出这个查询,它给了我预期的结果:

SELECT a.date, SUM(COALESCE(r.success_recipient, 0)), SUM(COALESCE(r.failed_recipient, 0))
FROM (
    SELECT curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) ) DAY AS date
    FROM (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
    cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d
) a
LEFT JOIN reports r ON a.date = r.report_date 
WHERE a.date between DATE_SUB(CURDATE(), INTERVAL 1 YEAR) and now() 
GROUP BY a.date;