在SQL中添加结果中的缺少日期

时间:2016-03-16 06:17:39

标签: sql postgresql

我有一个目前看起来像这样的数据库

Date     | valid_entry | profile
1/6/2015   1           | 1
3/6/2015   2           | 1
3/6/2015   2           | 2
5/6/2015   4           | 4

我正在尝试抓住日期,但我需要进行查询以显示列表中不存在的日期,例如2015年2月6日。

这是我需要的样本:

Date     | valid_entry
1/6/2015   1
2/6/2015   0
3/6/2015   2
3/6/2015   2
4/6/2015   0
5/6/2015   4 

我的查询:

select date, count(valid_entry)
from database
where profile = 1
group by 1;

此查询仅显示其中存在的日期。在查询中是否有一种方法可以使用那里不存在的日期填充结果?

2 个答案:

答案 0 :(得分:3)

您可以使用generate_series()生成源表中开始日期和结束日期之间所有日期的列表。然后可以在外部联接中使用这些日期来汇总所有日期的值。

with all_dates (date) as (
  select dt::date
  from generate_series( (select min(date) from some_table), (select max(date) from some_table), interval '1' day) as x(dt)
)
select ad.date, sum(coalesce(st.valid_entry,0))
from all_dates ad
  left join some_table st on ad.date = st.date
group by ad.date, st.profile
order by ad.date;  

some_table是您提供的示例数据表。

根据您的示例输出,您似乎还希望按date profile分组,否则2015-06-03不能有两行。您似乎也不想要where profile = 1,因为它也不会生成2015-06-03的两行,如示例输出中所示。

SQLFiddle示例:http://sqlfiddle.com/#!15/b0b2a/2

不相关,但是:我希望列名只能组成。 date是列的可怕的名称。一个是因为它也是一个关键字,但更重要的是它不是文档这个日期的用途。开始日期?结束日期?截止日期?修改日期?

答案 1 :(得分:0)

您必须使用日历表来实现此目的。在这种情况下,您可以创建一个包含所需表格的内联表格,然后LEFT JOIN您的表格:

select "date", count(valid_entry)
from (
   SELECT '2015-06-01' AS d UNION ALL '2015-06-02' UNION ALL '2015-06-03' UNION ALL
          '2015-06-04' UNION ALL '2015-06-05' UNION ALL '2015-06-06') AS t
left join database AS db on t.d = db."date" and db.profile = 1
group by t.d;

注意:谓词profile = 1应该应用于ON操作的LEFT JOIN子句中。如果它放在WHERE子句中,那么LEFT JOIN基本上会成为INNER JOIN