MySQL: поиск пропущенных дат в диапазоне дат - PullRequest
3 голосов
/ 01 июля 2011

Мне нужна помощь с запросом MySQL.У меня есть таблица БД, в которой есть данные с 1 января 2011 года по 30 апреля 2011 года. Для каждой даты должна быть запись.Мне нужно выяснить, отсутствует ли какая-либо дата в таблице.

Так, например, допустим, что 2 февраля 2011 года нет данных.Как мне найти эту дату?

У меня есть даты, хранящиеся в столбце с именем reportdatetime.Даты хранятся в формате: 2011-05-10 0:00:00, то есть 5 мая 2011 г. 12:00:00.

Есть предложения?

Ответы [ 4 ]

7 голосов
/ 01 июля 2011

Это второй ответ, я выложу его отдельно.

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;

Это самообъединение, которое сообщает о такой дате, что не существует строки с последующей датой.

Это позволит найти первый день в промежутке, но если пропущено несколько дней, он не сообщит обо всех датах в промежутке.

5 голосов
/ 01 июля 2011
  1. CREATE TABLE Days (day DATE PRIMARY KEY);

  2. Заполните 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 столько раз, сколько необходимо. Он удваивает число строк каждый раз, поэтому вы можете получить строки за четыре месяца в семи INSERT.

  3. Выполните исключающее объединение, чтобы найти даты, для которых нет совпадений в таблице отчетов:

    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 голосов
/ 01 июля 2011

Если вы имеете в виду, что reportdatetime имеет запись "Feb 2, 2011", но другие поля, связанные с этой датой, отсутствуют, как показано в приведенной ниже таблице snap

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)
0 голосов
/ 01 июля 2011

Это может быть сделано с более сложным одиночным запросом, но я покажу псевдо код с временной таблицей только для иллюстрации:

Получить все даты, для которых у нас есть записи:

CREATE TEMP TABLE AllUsedDates

SELECT DISTINCT reportdatetime
INTO AllUsedDates;

Теперь добавьте 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
...