2011-02-04 83 views
4

我有一个名为logTime的日志字段的日志表。我需要显示日期范围内的行数和每天的记录数。问题是我仍然想显示没有记录按天分组,仍然显示没有行的日子?

只能用SQL才能做到这一点吗?

例子:

SELECT logTime, COUNT(*) FROM logs WHERE logTime >= '2011-02-01' AND logTime <= '2011-02-04' GROUP BY DATE(logTime);

它返回是这样的:

 
+---------------------+----------+ 
| logTime    | COUNT(*) | 
+---------------------+----------+ 
| 2011-02-01   |  2 | 
| 2011-02-02   |  1 | 
| 2011-02-04   |  5 | 
+---------------------+----------+ 
3 rows in set (0,00 sec) 

我想显示2011-02-03一天了。

回答

5

为了做到这一点,您需要有一个表格(或派生表格),其中包含可以使用LEFT JOIN加入的日期。

SQL对数学集的概念进行操作,并且如果您没有一组数据,则不需要SELECT。

如果您想了解更多详情,请相应评论。

5

MySQL不会为你发明行,所以如果数据不存在,它们自然不会显示。

您可以创建一个日历表,并在加入,

create table calendar (
    day date primary key, 
); 

填写此表的日期(易于使用的存储过程,或者只是一些普通的脚本),在这之前围绕2038和别的东西会可能打破成为问题的单位。

您的查询变成例如现在

SELECT logTime, COUNT(*) 
    FROM calendar cal left join logs l on cal.day = l.logTime 
WHERE day >= '2011-02-01' AND day <= '2011-02-04' GROUP BY day; 

,你可以与其他列延伸日历表,告诉你的月份,年份,星期等,这样你就可以很容易地生产用于其他时间单位的统计数据。 (纯粹主义者可能会争辩日历表将有一个id整数主键日志表引用,而不是日期)

+1

我会考虑这个最“正确”的答案。 – gahooa 2011-02-04 21:25:07

1

我不确定这是否应该由SQL解决的问题。正如其他人所表明的那样,这需要保持第二个表,其中包含给定时间跨度的各个日期的所有,其必须在每次时间跨度增加时更新(如果该时间跨度是。当前时间

相反,你应该用它来检查查询的结果,并在必要时注资日期,这是完全动态的,不需要任何中间表既然你没有指定语言,这里是伪代码:

EXECUTE QUERY `SELECT logTime, COUNT(*) FROM logs WHERE logTime >= '2011-02-01' AND logTime <= '2011-02-04' GROUP BY DATE(logTime);` 

FOREACH row IN query result 
    WHILE (date in next row) - (date in this row) > 1 day THEN 
    CREATE new row with date = `date in this row + 1 day`, count = `0` 
    INSERT new row IN query result AFTER this row 
    ADVANCE LOOP INDEX TO new row (`this row` is now the `new row`) 
    END WHILE 
END FOREACH 

或类似的东西