[英]Get count of created entries for each day
Let's say I have a this search query like this: 假设我有一个这样的搜索查询:
SELECT COUNT(id), date(created_at)
FROM entries
WHERE date(created_at) >= date(current_date - interval '1 week')
GROUP BY date(created_at)
As you know then for example I get a result back like this: 如你所知,例如我得到一个像这样的结果:
count | date
2 | 15.01.2014
1 | 13.01.2014
9 | 09.01.2014
But I do not get the days of the week where no entries where created. 但我没有得到一周没有创建条目的日子。
How can I get a search result that looks like this, including the days where no entries where created? 如何获得看起来像这样的搜索结果, 包括没有创建条目的日期?
count | date
2 | 15.01.2014
0 | 14.01.2014
1 | 13.01.2014
0 | 12.01.2014
0 | 11.01.2014
0 | 10.01.2014
9 | 09.01.2014
SELECT day, COALESCE(ct, 0) AS ct
FROM (SELECT now()::date - d AS day FROM generate_series (0, 6) d) d -- 6, not 7
LEFT JOIN (
SELECT created_at::date AS day, count(*) AS ct
FROM entries
WHERE created_at >= date_trunc('day', now()) - interval '6d'
GROUP BY 1
) e USING (day);
Use a sargable expression for your WHERE
condition, so Postgres can use a plain index on created_at
. 对
WHERE
条件使用sargable表达式,因此Postgres可以在created_at
上使用普通索引。 Far more important for performance than all the rest. 对性能而言比其他所有人都重要得多。
To cover a week (including today), subtract 6 days from the start of "today", not 7. 为了覆盖一周(包括今天),从“今天”开始减去6天,而不是7天。
Assuming that id
is defined NOT NULL
, count(*)
is identical to count(id)
here, but slightly faster. 假设
id
被定义为NOT NULL
, count(*)
count(id)
在这里与count(id)
相同,但稍快一些。
A CTE would be overkill here. CTE在这里会有点矫枉过正。 It's slower and more verbose.
它更慢,更冗长。
Aggregate first, join later. 首先聚合,稍后加入。 That's faster in this case.
在这种情况下,这更快。
now()
is the slightly shorter and faster Postgres implementation of the standard SQL CURRENT_TIMESTAMP
(which you can use as well). now()
是标准SQL CURRENT_TIMESTAMP
的稍微更短和更快的Postgres实现(您也可以使用它)。
This should be the shortest and fastest query. 这应该是最短和最快的查询。 Test with
EXPLAIN ANALYZE
. 使用
EXPLAIN ANALYZE
测试。
Related: 有关:
Try this query: 试试这个查询:
with a as (select current_date - n as dt from generate_series(0, 6) as t(n)),
b as (select count(id) cnt, date(created_at) created_at
from entries
where date(created_at) >= date(current_date - interval '1 week')
group by date(created_at))
select coalesce(b.cnt,0), a.dt
from a
left join b on (a.dt = b.created_at)
order by a.dt;
count
function will not generate 0 for non-existing rows. count
函数不会为不存在的行生成0。 So you have to fill the rows for missing dates. 所以你必须填写缺少日期的行。 With
generate_series
and simple date arithmetic, you can generate rows for dates of some period (in this case, 1 week). 使用
generate_series
和简单的日期算法,您可以为某段时间的日期生成行(在本例中为1周)。 Then you can outer join to generate the final result. 然后,您可以通过外连接生成最终结果。
coalesce
will substitute null
to 0
. coalesce
将null
替换为0
。
You need to tell SQL to handle NULL. 您需要告诉SQL处理NULL。 Return
0
if NULL
如果为
NULL
返回0
You can do this by COALESCE
你可以通过
COALESCE
来做到这一点
http://www.postgresql.org/docs/devel/static/functions-conditional.html http://www.postgresql.org/docs/devel/static/functions-conditional.html
Use generate_series()
to create the dates you need and JOIN to this list of dates: 使用
generate_series()
创建所需的日期并加入此日期列表:
SELECT COUNT(id),
date(gdate)
FROM entries
RIGHT JOIN generate_series(current_date - interval '1 week', current_date, '1 day') g(gdate)
ON date(created_at) = date(gdate) AND date(created_at) >= date(current_date - interval '1 week')
GROUP BY
date(gdate)
ORDER BY
date(gdate) DESC;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.