Выберите записи, где дата не в таблице нескольких диапазонов дат SQL Server - PullRequest
2 голосов
/ 02 февраля 2012

У меня есть таблица в SQL Server, которая содержит различные диапазоны дат.

Таблица имеет дату начала и дату окончания, как показано ниже: -

start_date                  end_date
=======================     =======================
2011-02-21 00:00:00.000     2011-02-25 00:00:00.000
2011-04-18 00:00:00.000     2011-04-29 00:00:00.000
2011-05-31 00:00:00.000     2011-06-03 00:00:00.000
2011-07-21 00:00:00.000     2011-08-31 00:00:00.000
2011-10-24 00:00:00.000     2011-10-28 00:00:00.000
2011-12-19 00:00:00.000     2012-01-02 00:00:00.000
2012-02-13 00:00:00.000     2012-02-17 00:00:00.000
2012-04-02 00:00:00.000     2012-04-13 00:00:00.000
2012-06-04 00:00:00.000     2012-06-08 00:00:00.000
2012-07-20 00:00:00.000     2012-08-31 00:00:00.000
2012-10-29 00:00:00.000     2012-11-02 00:00:00.000
2012-12-24 00:00:00.000     2013-01-01 00:00:00.000
2013-02-10 00:00:00.000     2013-02-16 00:00:00.000
2013-03-24 00:00:00.000     2013-04-06 00:00:00.000
2013-05-26 00:00:00.000     2013-06-01 00:00:00.000
2013-07-24 00:00:00.000     2013-08-31 00:00:00.000
2013-10-27 00:00:00.000     2013-11-02 00:00:00.000

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

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

Моя первоначальная идея состоит в том, чтобы РАСШИРИТЬ все даты из вышеуказанных диапазонов, затем выполнить ВЫБОР, ГДЕ НЕ СУЩЕСТВУЕТ, или есть более эффективный способ достижения этого?

Ответы [ 5 ]

4 голосов
/ 02 февраля 2012
SELECT t.* 
FROM AnotherTable t 
WHERE NOT EXISTS(
    SELECT 1 
    FROM TblDate d 
    WHERE d.start_date <= t.DateColumn
    AND   d.end_date   >= t.DateColumn
)

Редактировать : Просто видел, что это была ваша первоначальная идеяПоэтому я предполагаю, что это самый простой и быстрый подход.Вот что почитать на эту тему:

http://sqlserverperformance.idera.com/tsql-optimization/finding-nonexistent-records-hurry/

1 голос
/ 02 февраля 2012

Вам необходимо проверить 2 условия: 1. Дата находится в диапазоне 2. Дата имеет тот же день, что и дата начала, но была позже, чем дата окончания (у вас нет часов, минут и секунд вдиапазон)

SELECT * FROM VALUE_TABLE
LEFT JOIN DATE_RANGE_TABLE ON 
  YEAR(VALUE_TABLE.CHECK_DATE) = YEAR(start_date)
  and MONTH (VALUE_TABLE.CHECK_DATE) = MONTH (start_date)
  AND DAY (VALUE_TABLE.CHECK_DATE) = DAY (start_date)
  OR VALUE_TABLE.CHECK_DATE BETWEEN start_date and end_date
WHERE start_date IS NULL
1 голос
/ 02 февраля 2012

Ниже приведен более эффективный, чем ваше предложение с (я думаю) с тем же конечным результатом.Единственное, в чем я не уверен, так это в том, что я понял, что ваши критерии относительно даты начала равны дате окончания, а затем исключают весь день.

SELECT  *
FROM    Table1
        LEFT JOIN
        (   SELECT  Start_date, CASE WHEN End_Date = Start_Date THEN DATEADD(MILLISECOND, -1, DATEADD(DAY, 1, End_Date)) ELSE End_Date END [End_Date]
            FROM    table2
        ) Exc
            ON table.DateColumn BETWEEN Exc.Start_Date AND Exc.End_Date
WHERE   Exc.Start_Date IS NULL
1 голос
/ 02 февраля 2012

Вы можете выполнить левое соединение с таблицей диапазонов и добавить предложение where, отфильтровывая любые совпадения.

SELECT anothertable.* FROM anothertable
LEFT JOIN range on anothertable.date >= range.start_date and anothertable.date <= range.end_date
WHERE range.start_date IS NULL
0 голосов
/ 02 апреля 2018
select * from anothertable
WHERE NOT EXISTS (SELECT 1 FROM range 
                   WHERE anothertable.date BETWEEN range.start_date AND range.end_date)

Используйте BETWEEN вместо <= and >=

...