MySQL如何填充范围内的缺失日期?

标签 mysql sql recursive-query gaps-and-islands date-arithmetic

我有一个包含 2 列、日期和分数的表格。它最多有 30 个条目,过去 30 天中的每一天都有一个。

date      score
-----------------
1.8.2010  19
2.8.2010  21
4.8.2010  14
7.8.2010  10
10.8.2010 14

我的问题是缺少一些日期 - 我想看看:

date      score
-----------------
1.8.2010  19
2.8.2010  21
3.8.2010  0
4.8.2010  14
5.8.2010  0
6.8.2010  0
7.8.2010  10
...

我需要从单个查询中得到:19,21,9,14,0,0,10,0,0,14... 这意味着缺失的日期用 0 填充。

我知道如何获取所有值并使用服务器端语言迭代日期并丢失空格。但这是否可以在 mysql 中执行,以便我按日期对结果进行排序并获取丢失的部分。

编辑:在这个表中还有一个名为 UserID 的列,所以我有 30.000 个用户,其中一些在这个表中有分数。如果日期 < 30 天前,我每天都会删除日期,因为我需要每个用户最近 30 天的分数。原因是我正在制作过去 30 天的用户事件图表,并且要绘制图表,我需要用逗号分隔的 30 个值。所以我可以在查询中说让我得到 USERID=10203 事件,查询会得到 30 个分数,过去 30 天中的每一天都有一个分数。我希望我现在更清楚了。

最佳答案

MySQL 没有递归功能,因此您只能使用 NUMBERS 表技巧 -

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

    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 `example`.`numbers`
      ( `id` )
    VALUES
      ( NULL )
    

    ...根据需要提供尽可能多的值。

  3. 使用DATE_ADD构建日期列表,根据 NUMBERS.id 值增加天数。将“2010-06-06”和“2010-06-14”替换为您各自的开始日期和结束日期(但使用相同的格式,YYYY-MM-DD)-

    SELECT `x`.*
      FROM (SELECT DATE_ADD('2010-06-06', INTERVAL `n`.`id` - 1 DAY)
              FROM `numbers` `n`
             WHERE DATE_ADD('2010-06-06', INTERVAL `n`.`id` -1 DAY) <= '2010-06-14' ) x
    
  4. 根据时间部分左连接到您的数据表中:

       SELECT `x`.`ts` AS `timestamp`,
              COALESCE(`y`.`score`, 0) AS `cnt`
         FROM (SELECT DATE_FORMAT(DATE_ADD('2010-06-06', INTERVAL `n`.`id` - 1 DAY), '%m/%d/%Y') AS `ts`
                 FROM `numbers` `n`
                WHERE DATE_ADD('2010-06-06', INTERVAL `n`.`id` - 1 DAY) <= '2010-06-14') x
    LEFT JOIN TABLE `y` ON STR_TO_DATE(`y`.`date`, '%d.%m.%Y') = `x`.`ts`
    

如果要保持日期格式,请使用 DATE_FORMAT function :

DATE_FORMAT(`x`.`ts`, '%d.%m.%Y') AS `timestamp`

关于MySQL如何填充范围内的缺失日期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3538858/

相关文章:

mysql - TeamSpeak3 服务器迁移

没有子查询的 MySQL 组内聚合 - 建议的测试数据已更新

mysql - 如何创建MySQL分层递归查询

mysql - 需要关于映射关键字关系的数据库技术和方法建议

mysql - LEFT JOIN 在 "FROM"部分的多个表上

php - call_user_func_array 不适用于 php 5.6

mysql - 优秀的开源 MariaDB 前端

sql - 如何根据 Snowflake 中的列进行分层

sql - 在 SQL 中选择连续的数字

sql - 滑动1小时周期聚合查询