Mysql 查找缺失的日期范围

标签 mysql sql database

我有一个包含日期范围的表格:

    create table d (
    date_start date,
    date_end date
    );

    insert into d values('2014-03-05', '2014-04-10');
    insert into d values('2014-05-01', '2014-06-05');
    insert into d values('2014-07-10', '2014-08-15');

我想完成此表,但缺少 2014 年的日期范围。在本例中,情况为:

    2014-01-01 - 2014-03-04
    2014-04-11 - 2014-04-30
    2014-06-06 - 2014-07-09
    2014-08-16 - 2014-12-31

有什么mysql查询建议吗?

编辑

更好地使用这些值:

    create table d (
        date_start date,
        date_end date
        );

        insert into d values('2014-06-01', '2014-06-30');
        insert into d values('2014-07-01', '2014-08-03');
        insert into d values('2014-09-01', '2014-09-30');

编辑2

我快要完成了:

    SELECT
            date_start,
            date_end

    FROM

    (SELECT 
      ends.point AS date_start,
      starts.point AS date_end
    FROM 
      (SELECT 
        d.date_end+INTERVAL 1 DAY AS point, 
        @n:=@n+1 AS num 
      FROM 
        d 
          CROSS JOIN (SELECT @n:=1) AS init0
          ORDER BY date_start
      ) AS ends 
      INNER JOIN 
      (SELECT 
        d.date_start-INTERVAL 1 DAY AS point, 
        @m:=@m+1 AS num 
      FROM 
        d 
          CROSS JOIN (SELECT @m:=0) AS init1
          ORDER BY date_start
      ) AS starts 
      ON ends.num=starts.num
    UNION ALL 
      SELECT 
      '2014-01-01', 
        MIN(date_start) - INTERVAL 1 DAY 
      FROM 
        d 
      WHERE 
        date_start>='2014-01-01'
    UNION ALL 
      SELECT 
        MAX(date_end)+INTERVAL 1 DAY, 
        '2014-12-31'
      FROM
        d 
      WHERE 
        date_end <= '2014-12-31'
    ) as dates
    WHERE
      date_start < date_end
    ORDER BY 
      date_start;

但是,对于以下设置的间隔,此查询返回错误结果:

    create table d (date_start date, date_end date);

    insert into d values('2014-01-01', '2014-01-09');
    insert into d values('2014-01-10', '2014-03-15');
    insert into d values('2014-03-16', '2014-04-20');
    insert into d values('2014-05-01', '2014-07-30');
    insert into d values('2014-08-01', '2014-09-30');
    insert into d values('2014-12-25', '2014-12-31');

它似乎无法处理像 2014-07-31 - 2014-07-31 这样的单日。

最佳答案

如果您的日期间隔不会嵌套或相交,您可以使用 JOIN 技巧来生成结果集。因此,要选择所需的记录集,您需要:

SELECT
  *
FROM
(SELECT 
  ends.point AS date_start, 
  starts.point AS date_end 
FROM 
  (SELECT 
    d.date_end+INTERVAL 1 DAY AS point, 
    @n:=@n+1 AS num 
  FROM 
    d 
      CROSS JOIN (SELECT @n:=1) AS init0
  ) AS ends 
  INNER JOIN 
  (SELECT 
    d.date_start-INTERVAL 1 DAY AS point, 
    @m:=@m+1 AS num 
  FROM 
    d 
      CROSS JOIN (SELECT @m:=0) AS init1
  ) AS starts 
  ON ends.num=starts.num 
UNION ALL 
  SELECT 
    '2014-01-01', 
    MIN(date_start) - INTERVAL 1 DAY AS date_end
  FROM 
    d 
  HAVING 
    date_end>'2014-01-01' 
UNION ALL 
  SELECT 
    MAX(date_end)+INTERVAL 1 DAY AS date_start, 
    '2014-12-31' 
  FROM
    d 
  HAVING 
    date_start<'2014-12-31' 
) as dates
WHERE
  date_start<=date_end
ORDER BY 
  date_start;

这将导致

+------------+------------+
| date_start | date_end   |
+------------+------------+
| 2014-01-01 | 2014-03-04 |
| 2014-04-11 | 2014-04-30 |
| 2014-06-06 | 2014-07-09 |
| 2014-08-16 | 2014-12-31 |
+------------+------------+

(fiddle 在这里)

要“完成”您的表格,您可以使用 INSERT..SELECT上面的 SELECT 查询语法。

关于Mysql 查找缺失的日期范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23949227/

相关文章:

php - 如何在 laravel Eloquent 中将 int 转换为字符串?

mysql - 如何获取一张表的自增ID并插入到另一张表中

c# - 用户 'myUser' @'DESKTOP-1FSAS' 的访问被拒绝(使用密码 : NO)

ruby-on-rails - rails : sharing information between 2 apps

java - 为 giraph 运行 hive 作业以进行图形分析时出现问题

php - 有选择地将数据从一个表拆分并保存到另一个mysql

sql - SQL 事务的实际成本是多少?

php - 使用 phalcon 检查数据库中是否存在电子邮件

mysql - 在 MySQL 脚本中设置当前数据库

java - 如何在Java中从sql模式生成orm映射类