MySQL:查找日期范围之间的缺失日期

Posted

技术标签:

【中文标题】MySQL:查找日期范围之间的缺失日期【英文标题】:MySQL: Find Missing Dates Between a Date Range 【发布时间】:2011-07-01 17:19:40 【问题描述】:

我需要一些有关 mysql 查询的帮助。我有 db 表,其中包含 2011 年 1 月 1 日至 2011 年 4 月 30 日的数据。每个日期都应该有记录。我需要找出表格中是否缺少任何日期。

例如,假设 2011 年 2 月 2 日没有数据。我如何找到那个日期?

我将日期存储在名为 reportdatetime 的列中。日期的存储格式为:2011-05-10 0:00:00,即 2011 年 5 月 5 日凌晨 12:00:00。

有什么建议吗?

【问题讨论】:

所以您是说单个日期根本没有一行,或者它有一行并且另一列中没有数据?如果它没有一行,我能想到的唯一方法是遍历每个日期并检查它。 您的意思是 reportdatetime 有 2011 年 2 月 2 日的条目,但与该日期关联的其他字段不存在? 可能与***.com/questions/3538858/…重复 还有一个骗子***.com/questions/5522701/… 【参考方案1】:

这是第二个答案,我会单独发布。

SELECT DATE(r1.reportdate) + INTERVAL 1 DAY AS missing_date
FROM Reports r1
LEFT OUTER JOIN Reports r2 ON DATE(r1.reportdate) = DATE(r2.reportdate) - INTERVAL 1 DAY
WHERE r1.reportdate BETWEEN '2011-01-01' AND '2011-04-30' AND r2.reportdate IS NULL;

这是一个自联接,它报告一个日期,使得不存在具有以下日期的行。

这将找到间隔中的第一天,但​​如果缺少多天的运行,则不会报告间隔中的所有日期。

【讨论】:

稍微修改了它以解释导致自我加入疯狂的重复日期值:SELECT DISTINCT DATE(r1.date) + INTERVAL 1 DAY AS missing_date FROM mytable r1 LEFT OUTER JOIN (SELECT DISTINCT date FROM mytable ) r2 ON DATE(r1.date) = DATE(r2.date) - INTERVAL 1 DAY WHERE r1.date BETWEEN '2011-06-19' AND '2012-08-30' AND r2.date IS NULL 这项工作仅在缺少的日期是一天但如果您有多个日期则失败 @MartinVarta,是的,这是真的。我在上面的回答中已经说过了。 @BillKarwin 这个解决方案可以提供帮助,可以更改范围。 SELECT * FROM (SELECT DATE_ADD('2014-01-01', INTERVAL t4+t16+t64+t256+t1024 DAY) 缺失 FROM (SELECT 0 t4 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) t4, (SELECT 0 t16 UNION ALL SELECT 4 UNION ALL SELECT 8 UNION ALL SELECT 12 ) t16, (SELECT 0 t64 UNION ALL SELECT 16 UNION ALL SELECT 32 UNION ALL SELECT 48) t64, (SELECT 0 t256 UNION ALL SELECT 64 UNION ALL SELECT 128 UNION ALL SELECT 192) t256 ) b WHERE 缺失 NOT IN (SELECT fDesde262 FROM py262) AND ausente @MartinVarta,太好了,您为什么不将其发布为答案?【参考方案2】:

    CREATE TABLE Days (day DATE PRIMARY KEY);

    Days 中填写您要查找的所有日期。

    mysql> INSERT INTO Days VALUES ('2011-01-01');
    mysql> SET @offset := 1;
    mysql> INSERT INTO Days SELECT day + INTERVAL @offset DAY FROM Days; SET @offset := @offset * 2;
    

    然后向上箭头并根据需要重复插入多次。它每次将行数翻倍,因此您可以在七个 INSERT 中获得四个月的行数。

    执行排除联接以查找报告表中不匹配的日期:

    SELECT d.day FROM Days d 
    LEFT OUTER JOIN Reports r ON d.day = DATE(r.reportdatetime) 
    WHERE d.day BETWEEN '2011-01-01' AND '2011-04-30' 
        AND r.reportdatetime IS NULL;`
    

【讨论】:

嗨,比尔,感谢您的评论。正如 Sunny 所提到的,第 2 步将是一个挑战。除了手动之外,还有什么建议吗? 我用一个用 128 天的行填充表格的例子编辑了上面的内容。【参考方案3】:

这可以通过更复杂的单个查询来完成,但我将展示一个带有临时表的代码只是为了说明:

获取我们有记录的所有日期:

CREATE TEMP TABLE AllUsedDates

SELECT DISTINCT reportdatetime
INTO AllUsedDates;

现在添加 5 月 1 日,以便我们跟踪 04-30

INSERT INTO AllUsedData ('2011-05-01')

如果没有“第二天”,我们发现了一个差距:

SELECT A.NEXT_DAY
FROM
    (SELECT reportdatetime AS TODAY, DATEADD(reportdatetime, 1) AS NEXT_DAY FROM AllUsed Dates) AS A
WHERE
    (A.NEXT_DATE NOT IN (SELECT reportdatetime FROM AllUsedDates)
    AND
    A.TODAY <> '2011-05-01') --exclude the last day

【讨论】:

【参考方案4】:

如果您的意思是 reportdatetime 具有“2011 年 2 月 2 日”条目,但与该日期关联的其他字段不存在,如下表所示

reportdate  col1    col2
5/10/2011   abc xyz
2/2/2011        
1/1/2011    bnv oda

那么这个查询可以正常工作

select reportdate from dtdiff where reportdate not in (select df1.reportdate from dtdiff df1, dtdiff df2 where df1.col1 = df2.col1)

【讨论】:

嗨,拉胡尔,感谢您的留言。对不起,我没有更清楚。我的意思是 2011 年 2 月 2 日在表中没有条目。 reportdatetime 列中缺少它。 @Laximidi,在这种情况下,您必须在另一个表中填写 2011 年 1 月 1 日至 2011 年 4 月 30 日之间的所有日期,然后您可以通过发出查询 @987654323 轻松找到丢失的日期@【参考方案5】:

试试这个

SELECT DATE(t1.datefield) + INTERVAL 1 DAY AS missing_date FROM table t1 LEFT OUTER JOIN table t2 ON DATE(t1.datefield) = DATE(t2.datefield) - INTERVAL 1 DAY WHERE DATE(t1.datefield) BETWEEN '2020-01-01' AND '2020-01-31' AND DATE(t2.datefield) IS NULL;

如果您想在日期时间字段中获取缺失的日期,请使用此选项。

SELECT CAST(t1.datetime_field  as DATE) + INTERVAL 1 DAY AS missing_date FROM table t1 LEFT OUTER JOIN table t2 ON CAST(t1.datetime_field  as DATE) = CAST(t2.datetime_field  as DATE) - INTERVAL 1 DAY WHERE CAST(t1.datetime_field  as DATE) BETWEEN '2020-01-01' AND '2020-07-31' AND CAST(t2.datetime_field  as DATE) IS NULL;

【讨论】:

以上是关于MySQL:查找日期范围之间的缺失日期的主要内容,如果未能解决你的问题,请参考以下文章

mysql日期范围查找(两个日期之间的记录)

Mysql 跨行查找日期范围

Mysql - 使用多个连接表查找丢失的日期

SQL如何编写返回缺失日期范围的查询?

在haml中查找两个日期之间的范围

MySQL - 如何查找日期在开始日期到结束日期之间的记录