我有一张桌子
___________________________________________
id | user | Visitor | timestamp
___________________________________________
13 |username |abc | 2014-01-15 15:01:44
14 |username |abc | 2014-01-15 15:01:44
15 |username |abc | 2014-01-18 15:01:44
16 |username |abc | 2014-01-18 15:01:44
___________________________________________
我在今天的7天内使用QUERY来计算USER abc的访问者数量。
SELECT DATE(`timestamp`) as `date`, COUNT(*) as `count`
FROM `table` WHERE (`timestamp` >= (NOW() - INTERVAL 7 DAY)) AND (`user` = 'username')
GROUP BY `date`;
得到以下输出:
______________________________
date | count
______________________________
2014-01-15 | 2
2014-01-18 | 2
但我需要:
______________________________
date | count
______________________________
2014-01-15 | 2
2014-01-16 | 0 // Make 0 for the day which is not present
2014-01-17 | 0 // Make 0 for the day which is not present
2014-01-18 | 2
将对此进行查询?
答案 0 :(得分:3)
使用子查询创建一个包含过去一周所有日期的表格,然后将其与您的表格连接:
SELECT `date`, IFNULL(COUNT(*), 0) as `count`
FROM (SELECT DATE(NOW()) AS `date`
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 1 DAY))
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 2 DAY))
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 3 DAY))
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 4 DAY))
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 5 DAY))
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 6 DAY))
UNION
SELECT DATE(DATE_SUB(NOW(), INTERVAL 7 DAY))) AS days
LEFT JOIN `table` ON DATE(`timestamp`) = `date`
WHERE (`timestamp` >= (NOW() - INTERVAL 7 DAY)) AND (`user` = 'username')
GROUP BY `date`;
答案 1 :(得分:1)
这是关于gap的一个众所周知的问题 - 它在SO上有很多答案。
首先,最明显的方法是使用将连续保存所有日期的表(当前年份作为样本)例如,让它为dates
表,其中包含字段record_date
(它保存日期)那么你的查询将如下所示:
SELECT
DATE(`timestamp`) as `date`,
COUNT(`dates`.`id`) as `count`
FROM
`dates`
LEFT JOIN
`table`
ON `dates`.`record_date` = DATE(`table`.`timestamp`)
WHERE
(`timestamp` >= (NOW() - INTERVAL 7 DAY))
AND
(`user` = 'username')
GROUP BY
`dates`.`record_date`
- 你将强制通过LEFT JOIN
返回零。
使用序列生成器查询实现此目的还有另一种更复杂的方法。实际上,MySQL中没有序列,但您可以从CROSS JOIN
生成连续值,然后将它们应用于日期选择。例如:
SELECT
DATE_ADD(CURDATE() - INTERVAL 1 WEEK, INTERVAL sequence.id DAY)
FROM
(SELECT
(two_1.id + two_2.id + two_4.id +
two_8.id + two_16.id) AS id
FROM
(SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1
CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 2 AS id) AS two_2
CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 4 AS id) AS two_4
CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 8 AS id) AS two_8
CROSS JOIN (SELECT 0 AS id UNION ALL SELECT 16 AS id) AS two_16
) AS sequence
WHERE
sequence.id<7
- 前一周会produce dates,所以你将能够使用它,而不是像第一种方式那样创建和填充临时表。关于这个查询的好处是 - 它是静态的,因此如果你想增加选择间隔,你不必添加另一个UNION
部分。