【问题标题】:Records count per day, including 0 values每天记录数,包括 0 个值
【发布时间】:2019-08-04 06:32:02
【问题描述】:

我正在尝试获取一个显示过去 7 天每天访问次数的查询。我提出的查询有效,但它有我不知道如何摆脱的限制。

想象一下,现在是 2019 年 8 月 4 日。我们的表 visits 保存了用户访问网站的时间戳:

ID | timestamp
1 | 2019-08-03
2 | 2019-08-03
3 | 2019-08-02
4 | 2019-07-31
5 | 2019-07-31
6 | 2019-07-31
7 | 2019-07-31
8 | 2019-07-30
9 | 2019-07-30
10 | 2019-07-28

目标:获取过去 7 天每天访问网站的次数。所以结果应该是这样的:

DATE | NumberOfVisitis
2018-08-04 | 0
2018-08-03 | 2
2018-08-02 | 1
2018-08-01 | 0
2018-07-31 | 4
2018-07-30 | 1
2018-07-29 | 0

我的查询仅包括在 DB 中注册的日期(不包括没有访问的日期)。这是有道理的,因为查询依赖于数据,而不是日历。

SELECT DATE_FORMAT(`timestamp`, "%Y%m/%d") AS Date, COUNT(`id`) AS
NumberOfVisitis FROM `visits` WHERE `timestamp` >= DATE_ADD(NOW(),
INTERVAL -7 DAY) GROUP BY DAY(`timestamp`) ORDER BY `timestamp` DESC

您能否告诉我如何修改我的查询以在查询结果中包含没有访问的天数?

【问题讨论】:

  • 你需要日历..
  • 查看这个答案。问题是针对 postgresql 但应该适用于 mysql。 stackoverflow.com/questions/14793057/…
  • 考虑处理应用代码中数据显示(包括缺失数据)的问题

标签: mysql sql


【解决方案1】:

MySQL 缺少像 Postgres 的 generate_series 这样的东西,所以我们必须伪造它。

最简单的做法是制作一张包含一堆数字的表格。这对于生成很多东西很有用。

create table numbers ( number serial );
insert into numbers () values (), (), (), (), (), (), ();

从中我们可以生成最近 7 天的列表。

select date_sub(date(now()), interval number-1 day) as date
from numbers
order by number
limit 7

然后使用它作为 CTE(或子查询)我们 left join 访问它。左连接意味着所有日期都将存在。

with dates as (
    select date_sub(date(now()), interval number-1 day) as date
    from numbers
    order by number
    limit 7
)
select date, coalesce(sum(id), 0)
from dates
left join visits on date = timestamp
group by date
order by date

【讨论】:

  • 谢谢@Schwern。那太棒了!知道了。将采用这个概念并让它飞起来。
猜你喜欢
  • 2022-07-01
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多