SQL:过去7天内的总条目数,按日分组,如果当天没有条目将其设置为0

时间:2017-12-27 16:26:55

标签: mysql sql

我有一个包含以下列的表:

JsonEnum

我需要从今天起最后7天获得总数。

如果当天的总数为0 - 将其返回为0而不是根本不返回。

我试过这个:

id | time (SQL datetime) | url

但它从我的理解中返回每小时的总数 - 我不知何故需要将日期时间戳转换为日期?

我还在学习SQL。

1 个答案:

答案 0 :(得分:0)

这是一个非常有趣的问题,因为答案要比问题复杂得多。

通常,SQL并不像我们在普通编程语言中那样使用循环和任意长度列表并动态生成内容。它通常依赖于在表格中预先存在所有数据。

如果现有表中的所有日期都没有问题,那么只需使用GROUP BY。但是,在哪里获得表格中不存在的日期,用?显示0计数?

看看SO,过去曾讨论并列出了几个选项。

基本上归结为4种选择:

  • 使用具有预先构建的必要日期范围的临时或永久表。与所有SQL服务器兼容,但有点令人讨厌,另外需要记住保持范围表的更新;
  • 在SQL之外的编程语言中创建所需日期的列表,然后比较返回的值。根本不优雅;
  • 使用服务器端程序:不太便携,但相对容易 - 制作一个程序,返回一个行列表,其中包含您指定的过程中的日期作为过程的参数;
  • 使用其他SQL服务器端调整,例如变量。

在你的情况下,根据这个问题的答案:Get a list of dates between two dates,我自己会考虑使用MySQL变量,因为你需要包含数据表中不存在的日期,这可能不会起作用(至少我没有找到可行的解决方案)。

因此,使用列出的问题中的任何解决方案,您应该为过去7天的实际列表创建类似于表的内容,如下所示:

temporary table LASTDAYS
datetime D
-------------
2017-12-27
2017-12-26
2017-12-25
2017-12-24
2017-12-23
2017-12-22
2017-12-21

(订单在这里不重要)

然后你做:

SELECT DATE(LASTDAYS.D) AS D1, COUNT( YOURTABLE.id) AS num
FROM LASTDAYS LEFT OUTER JOIN YOURTABLE
ON DATE(YOURTABLE.time)=date(LASTDAYS.D)
GROUP BY D1;

(注意OUTER join

创建这样一个表的最简单方法是:

CREATE TEMPORARY TABLE LASTDAYS (D datetime);

INSERT INTO LASTDAYS VALUES (CURRENT_TIMESTAMP);
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 1 DAY));
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 2 DAY));
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 3 DAY));
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 4 DAY));
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 5 DAY));
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 6 DAY));

但是,这真的是暴力。虽然,因为你只需要7行,它甚至可以包含在你的SELECT中。我不确定,但也许如果它包含在BEGIN / END事务块中,那么临时表甚至不会在SELECT之间持续存在。