代码之家  ›  专栏  ›  技术社区  ›  Ian McIntyre Silber

按日期分组,即使找不到记录也返回行

  •  4
  • Ian McIntyre Silber  · 技术社区  · 14 年前

    我有一个查询,它将表中的所有条目分组,并按datetime列对它们进行分组。这一切都很好:

    SELECT SUM(  `value` ) AS  `sum` , DATE(`datetime`) AS  `dt``
    FROM  `entry` 
    WHERE entryid = 85
    AND DATETIME BETWEEN  '2010-01-01' AND '2010-03-01'
    GROUP BY `dt`
    ORDER BY `datetime`
    

    问题是,我需要它返回一行,即使找不到任何内容,并且将值设置为0。 我假设有一些MYSQL函数可以处理这个问题,但似乎找不到它。

    1 回复  |  直到 14 年前
        1
  •  8
  •   OMG Ponies    14 年前

    MySQL没有递归功能,所以只能使用数字表技巧-

    1. 创建一个只包含递增数字的表-使用自动递增很容易:

      DROP TABLE IF EXISTS `example`.`numbers`;
      CREATE TABLE  `example`.`numbers` (
        `id` int(10) unsigned NOT NULL auto_increment,
         PRIMARY KEY  (`id`)
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
      
    2. INSERT INTO NUMBERS
        (id)
      VALUES
        (NULL)
      

      …尽可能多的价值观。

    3. 使用 DATE_ADD 构建日期列表,根据数字.id价值观。将“2010-01-01”和“2010-03-01”替换为各自的开始和结束日期(但使用相同的格式YYYY-MM-DD)-

      SELECT x.*
        FROM (SELECT DATE_ADD('2010-01-01', INTERVAL n.id - 1 DAY)
                FROM numbers n
               WHERE DATE_ADD('2010-01-01', INTERVAL n.id -1 DAY) <= '2010-03-01' ) x
      
    4.    SELECT DATE(x.dt) AS dt,
                COALESCE(SUM(e.value), 0) AS sum_value
           FROM (SELECT DATE_ADD('2010-01-01', INTERVAL n.id - 1 DAY) AS dt
                   FROM numbers n
                  WHERE DATE_ADD('2010-01-01', INTERVAL n.id -1 DAY) <= '2010-03-01' ) x
      LEFT JOIN ENTRY e ON DATE(e.datetime) = x.dt
                       AND e.entryid = 85
       GROUP BY DATE(x.dt) 
      

    为什么是数字,而不是日期?

    简单-可以根据数字生成日期,如我提供的示例中所示。它还意味着使用一个表,而不是说每个数据类型使用一个表。