MySQL: Find Missing Dates Between a Date Range

后端 未结 5 596
天命终不由人
天命终不由人 2020-12-06 13:57

I need some help with a mysql query. I\'ve got db table that has data from Jan 1, 2011 thru April 30, 2011. There should be a record for each date. I need to find out whethe

相关标签:
5条回答
  • 2020-12-06 14:17
    1. CREATE TABLE Days (day DATE PRIMARY KEY);

    2. Fill Days with all the days you're looking for.

      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;
      

      Then up-arrow and repeat the INSERT as many times as needed. It doubles the number of rows each time, so you can get four month's worth of rows in seven INSERTs.

    3. Do an exclusion join to find the dates for which there is no match in your reports table:

      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;`
      
    0 讨论(0)
  • 2020-12-06 14:21

    This is a second answer, I'll post it separately.

    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;
    

    This is a self-join that reports a date such that no row exists with the date following.

    This will find the first day in a gap, but if there are runs of multiple days missing it won't report all the dates in the gap.

    0 讨论(0)
  • 2020-12-06 14:32

    It could be done with a more complicated single query, but I'll show a pseudo code with temp table just for illustration:

    Get all dates for which we have records:

    CREATE TEMP TABLE AllUsedDates
    
    SELECT DISTINCT reportdatetime
    INTO AllUsedDates;
    

    now add May 1st so we track 04-30

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

    If there's no "next day", we found a gap:

    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
    
    0 讨论(0)
  • 2020-12-06 14:39

    Try this

    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;
    

    If you want to get missing dates in a datetime field use this.

    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;
    
    0 讨论(0)
  • 2020-12-06 14:40

    If you mean reportdatetime has the entry of "Feb 2, 2011" but other fields associated to that date are not present like below table snap

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

    then this query works fine

    select reportdate from dtdiff where reportdate not in (select df1.reportdate from dtdiff df1, dtdiff df2 where df1.col1 = df2.col1)
    
    0 讨论(0)
提交回复
热议问题