2011-10-17 5 views
2

У меня есть таблица БД со следующей структуройSQL: Получить все недостающие записи даты из базы данных

id | dateCreated | numOfUsers 

Где типичный строка 1, «2011-10-13 12:00:00», 4

В моей строке содержатся данные за последние 4 месяца, однако не хватает нескольких дней, и я хотел бы узнать, как использовать SQL в те дни, какие идеи я собираюсь написать для этого запроса?

Я подозреваю, что вы так поступили, так как получили список дней и сравнили их со значениями в базе данных.

Я знаю, что вы можете сделать это, используя PHP или другой язык программирования, используя несколько запросов, однако я бы хотел сделать это на уровне базы данных, если это возможно.

Заранее спасибо

+2

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

+3

Различные базы данных, разные ответы - выберите один, хотя на SO есть множество дубликатов. –

ответ

0

Легко наиболее эффективный способ (на мой взгляд), как вы утверждаете, чтобы начать с таблицей всех дат. Вы должны создать это самостоятельно, и предполагая, что вы сделали, вот несколько вариантов для вас ...

SELECT 
    * 
FROM 
    calendar -- Your manually created table of dates 
LEFT JOIN 
    yourTable 
    ON yourTable.DateField = calendar.DateField 
WHERE 
    yourTable.DateField IS NULL 
    AND calendar.DateField >= @reportFirstDate 
    AND calendar.DateField <= @reportLastdate 

Или ...

SELECT 
    * 
FROM 
    calendar -- Your manually created table of dates 
WHERE 
    NOT EXISTS (SELECT * FROM yourTable WHERE yourTable.DateField = calendar.DateField) 
    AND calendar.DateField >= @reportFirstDate 
    AND calendar.DateField <= @reportLastdate 

EDIT

Хотя он может чувствовать «неопрятный», сохраняя этот список дат, он обладает преимуществами Massive для такого типа запросов.

С таблицей дат вы просматриваете два индекса и проверяете, что существует в одном, но не другом.

Без таблицы дат у вас есть гораздо более сложный подход ...
1. Возьмите каждую запись в таблице
2. автообъединение его к следующей записи в таблице
3. Если они являются последовательными даты, отбросить их (вести учет с разрывом между ними)
4. Для каждой пары проведите через пропущенные, заполняя недостающие даты
5. С датой, отсутствующей в начале отчетного периода (без даты 1))
6. С датой, отсутствующей в конце отчетного периода (Нет даты2 в парах)

Возможно, на самом деле быстрее создать временную таблицу с датами, чтобы сделать это прямолинейно, а затем удалить таблицу снова. И если это так, почему бы вам просто не поддерживать таблицу дат?

  1. Просто стол на 100 лет, и забыть об этом
  2. Есть очень быстрые немного коды, чтобы сохранить даты до даты во все коде


Если вы не уверены, я бы рекомендовал опробовать различные варианты и убедиться в том, насколько быстрее таблица индексированных дат сравнивается с другими параметрами.

(Не говоря уже о том, как много короче, читабельности и поддержки)

+0

Спасибо за ваш ответ, однако мне не нравится идея таблицы, полной календарных дней, так как это означает, что мне придется обновлять таблицу так часто с новыми днями, которые нет в календаре. – phpNutt

+0

Google определяет размер даты, вы найдете любое количество сценариев, которые составят таблицу дат для вас на основе даты начала и окончания. Вы можете заполнить его в течение следующих 20 лет, если хотите. – OTTA

+0

SQL - это язык, основанный на SET. Чтобы найти сущности, которые существуют в одном наборе, но не другие, «в удобном для SQL», вам нужно, чтобы оба набора существовали. Накладные расходы на создание этой таблицы крошечные по сравнению с альтернативными подходами. (Один день стоит обычно 4 или 8 байтов, примерно четверть мегабайта за 100 лет) ... – MatBailie

1

AFAIK есть не одна заявление для достижения этой цели работает для всех баз данных ... для Oracle вы можете сделать это (MyTable это таблица БД вы хотите чтобы проверить пропущенные даты):

SELECT * FROM 
(
SELECT A.MinD + MyList.L TheDate FROM 
(SELECT MIN (dateCreated) MinD FROM MyTable) A, 
(SELECT LEVEL - 1 L FROM DUAL CONNECT BY LEVEL <= (SELECT Max (dateCreated) - MIN (dateCreated) + 1 FROM MyTable)) MyList 
) D WHERE D.TheDate NOT IN (SELECT dateCreated FROM MyTable T) 
1

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

SELECT @last := 'date you want to start with'; 

SELECT id, dateCreated, DATE_DIFF(dateCreated, @last) AS diff, @last := dateCreated 
FROM yourtable 
ORDER BY dateCreated ASC 
HAVING diff > 1 

Обратите внимание, что это не вернет фактические отсутствующие дни, но оно вернет строки ПОСЛЕ отсутствующих дат, а также количество отсутствующих дней.

2

Для PostgreSQL генерации "список дат" на лету довольно легко с помощью generate_series функции():

with all_dates as (
    select cast((current_date - interval '4' month) as date) + i as the_date 
    from generate_series(0, extract(day from current_date - (current_date - interval '4' month))::int) as i 
) 
select ad.the_date, 
     y.id, 
     y.numOfUsers 
from all_dates t 
    left join your_table y ON y.dateCreated = t.the_date; 
0

MySQL:

предполагая, что мы имеем таблицу yourTable и поле даты d:

set @day = 0; 

select v.y as `month`, v.m as `month`, v.d as `day` 
from 
(
    select y_m.y, Y_m.m, dd.d 
    from 
    (
    select distinct year(d) y, month(d) m, DAY(LAST_DAY(yourTable.d)) max_days from yourTable 
    ) y_m, 
    (
    select @day := @day+1 as `d` 
    from 
    information_schema.tables 
    limit 32 
    ) dd 
    where y_m.max_days >= dd.d 
) v 
left join 
    yourTable on (year(yourTable.d) = v.y and month(yourTable.d) = v.m and day(yourTable.d) = v.d) 
where yourTable.d is null 
; 
1

Существует способ сделать это без таблицы дат, дат начала и окончания или любой другой формы итерации.

select DATEADD(day,1,left.dateCreated) as MissingDates 
from dbo.MyTable as left 
left outer join dbo.MyTable as right on DATEADD(day,1,left.dateCreated) = right.entry_time 
where right.dateCreated is null 

Это вернет колонку дат начала для пропусков отсутствующих дат. Затем вы можете создать еще один столбец, который возвращает последнюю дату в промежутке отсутствующих дат, вычитая 1 вместо добавления одного дня во вторую сравнительную таблицу.

Смежные вопросы