MySQL:即使没有日期记录,如何获取记录?

时间:2014-11-26 17:33:23

标签: mysql sql

我每天都会获得生成图表的访问次数。即使记录为零,我也希望记录数为0。

我打算创建一个每天都会包含的表,在获取时 - 数据将与此表连接并从访问表中获取记录的计数。在mySQL中有没有其他方法可以做同样的事情?

访问带有样本数据的表

Date       | ........  
----------------------
01/11/2014 | --------
03/11/2014 | --------

我希望结果甚至是02/11/2014,计数为0.如果我按日期分组 - 只有在特定日期存在记录时才会计算。

1 个答案:

答案 0 :(得分:0)

我会尝试在你的问题的各行之间进行阅读...我写下问题和答案的游戏类型: - /

您有一个表(my_stats),其中包含两个字段,一个是日期(my_date),另一个是整数(my_counter)。

从某种意义上说,您需要一个表格,其中包含您要在输出中使用的所有日期的列表。 这可以使用临时表...(但并非所有托管解决方案都允许您这样做)另一个是使用视图或存储过程动态构建它。 然后,您将根据日期字段将此表/视图/存储过程/ etc ...左键加入到您的表my_visits中。 这将输出所有日期,当mour my_visits中没有匹配时,您将具有NULL值。 (IFNULL(my_visits.my_counter, 0)在没有匹配值时会给出0(零)。

启示: Get a list of dates between two dates + How to get list of dates between two dates in mysql select query这是一个不错的解决方案,不需要循环,过程或临时表generate days from date range

基于最后一个链接,我们在这里......

首先是一个样本表

DROP TABLE IF EXISTS `my_stats`;
CREATE TABLE IF NOT EXISTS `my_stats` (
  `my_date` date NOT NULL,
  `my_counter` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

INSERT INTO `my_stats` (`my_date`, `my_counter`) VALUES
('2017-11-01', 2),
('2017-11-02', 3),
('2017-11-03', 5),
('2017-11-05', 3),
('2017-11-07', 7);

现在是一个有效的例子BETWEEN '2017-11-01' AND '2017-11-09'

SELECT date_range.date                AS the_date, 
       IFNULL(my_stats.my_counter, 0) AS the_counter 
FROM (
    SELECT a.date 
    FROM (
        SELECT Curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) day 
                   AS date 
            FROM (
                SELECT 0 AS a 
                    UNION ALL 
                    SELECT 1 
                    UNION ALL 
                    SELECT 2 
                    UNION ALL 
                    SELECT 3 
                    UNION ALL 
                    SELECT 4 
                    UNION ALL 
                    SELECT 5 
                    UNION ALL 
                    SELECT 6 
                    UNION ALL 
                    SELECT 7 
                    UNION ALL 
                    SELECT 8 
                    UNION ALL 
                    SELECT 9
                ) AS a 
                CROSS JOIN (
                    SELECT 0 AS a 
                       UNION ALL 
                       SELECT 1 
                       UNION ALL 
                       SELECT 2 
                       UNION ALL 
                       SELECT 3 
                       UNION ALL 
                       SELECT 4 
                       UNION ALL 
                       SELECT 5 
                       UNION ALL 
                       SELECT 6 
                       UNION ALL 
                       SELECT 7 
                       UNION ALL 
                       SELECT 8 
                       UNION ALL 
                       SELECT 9
                ) AS b 
                CROSS JOIN (
                    SELECT 0 AS a 
                       UNION ALL 
                       SELECT 1 
                       UNION ALL 
                       SELECT 2 
                       UNION ALL 
                       SELECT 3 
                       UNION ALL 
                       SELECT 4 
                       UNION ALL 
                       SELECT 5 
                       UNION ALL 
                       SELECT 6 
                       UNION ALL 
                       SELECT 7 
                       UNION ALL 
                       SELECT 8 
                       UNION ALL 
                       SELECT 9
                    ) AS c
                ) AS a 
    WHERE  a.date BETWEEN '2017-11-01' AND '2017-11-09'
    ) AS date_range 
   LEFT JOIN my_stats 
          ON( date_range.date = my_stats.my_date ) 
ORDER  BY the_date ASC

输出

+------------+-------------+
| the_date   | the_counter |
+------------+-------------+
| 2017-11-01 |           2 |
| 2017-11-02 |           3 |
| 2017-11-03 |           5 |
| 2017-11-04 |           0 |
| 2017-11-05 |           3 |
| 2017-11-06 |           0 |
| 2017-11-07 |           7 |
| 2017-11-08 |           0 |
| 2017-11-09 |           0 |
+------------+-------------+