我有一个目前看起来像这样的数据库
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;
此查询仅显示其中存在的日期。在查询中是否有一种方法可以使用那里不存在的日期填充结果?
答案 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
。