简体   繁体   English

获取每天创建的条目的数量

[英]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 NULLcount(*) 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 . coalescenull替换为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM