Postgres空行的默认聚合值

时间:2018-01-13 17:01:10

标签: sql postgresql aggregate-functions outer-join

我写了一个查询,它正在进行X的聚合。

从本周一到周一开始。

select 
  extract(dow from time_sent) days
  , count(id)
from messages
where time_sent between date_trunc('week', now()) and now()
group by days
order by days;

我想知道如何在星期一没有添加行的情况下为星期一设置默认值。

即 星期一是空的,所以我得到了这个:

[ anonymous { day: 2, count: '1' },
  anonymous { day: 3, count: '1' },
  anonymous { day: 4, count: '1' },
  anonymous { day: 5, count: '1' },
  anonymous { day: 6, count: '1' } ]

预期结果:

[ anonymous { day: 1, count: '0' },
  anonymous { day: 2, count: '1' },
  anonymous { day: 3, count: '1' },
  anonymous { day: 4, count: '1' },
  anonymous { day: 5, count: '1' },
  anonymous { day: 6, count: '1' } ]

编辑:添加表格结构和示例输出。

id | time_sent 
1  | 2018-01-13 15:26:21.443828+08
2  | 2018-01-12 15:26:21.44755+08
3  | 2018-01-11 15:26:21.459208+08
4  | 2018-01-10 15:26:21.440648+08
5  | 2018-01-09 15:26:21.457262+08

查询#1:

select 
  coalesce(extract(dow from time_sent), d) days
  , count(message_batch_id)
from generate_series(0,6) d
left join messages 
on d = extract(dow from time_sent)
where time_sent between date_trunc('week', now()) and now()
group by days
order by days;

查询#1输出:

days | count
2    | 1
3    | 1
4    | 1
5    | 1
6    | 1

编辑:我需要澄清messages表在周一没有任何行条目。

编辑:

由于某种原因,此查询返回我想要的行结构:

select 
    extract(dow from d.*) days, 
    count(id) 
from GENERATE_SERIES(DATE_TRUNC('WEEK', NOW()), NOW(), '1 
DAY'::INTERVAL) d
left outer join messages m
on m.time_sent::DATE = d
group by days
order by days;

3 个答案:

答案 0 :(得分:0)

尝试:

select 
  coalesce(extract(dow from time_sent),d) days
  , count(id)
from generate_series(0,6) d
left outer join messages on d = extract(dow from time_sent)
where time_sent between date_trunc('week', now()) and now()
group by days
order by days;

(未测试)

答案 1 :(得分:0)

谓词不能扩展行。您必须使用GENERATE_SERIES生成日期,并将其加入messages

SELECT extract(dow from time_sent) days, coalesce(count(id), 0)
FROM GENERATE_SERIES(DATE_TRUNC('WEEK', NOW()), NOW(), '1 DAY'::INTERVAL) d 
    LEFT JOIN messages ON time_sent::DATE = d
GROUP BY days
ORDER BY days;

答案 2 :(得分:0)

出于某种原因,这会返回我期待的结果。 即,

返回一周中某一天的行(即使该特定日期没有行条目)

select 
    extract(dow from d.*) days, 
    count(id) 
from GENERATE_SERIES(DATE_TRUNC('WEEK', NOW()), NOW(), '1 
DAY'::INTERVAL) d
left outer join messages m
on m.time_sent::DATE = d
group by days
order by days;