2009-05-11 1 views
2

Этот запрос принимает долгое время, когда ENDDATE равно нулю (я думаю, что его о сазе до сазе это быстро)Как ускорить это утверждение: «paramDate Между startDate и NULL»?

SELECT * 
FROM HastaKurumlari 
WHERE CONVERT(SMALLDATETIME,'21-05-2009',103) 
BETWEEN startDate 
    AND (CASE WHEN endDate IS NULL THEN GETDATE() ELSE endDate END) 

Что я должен использовать, когда ENDDATE равно нулю, чтобы сделать это быстрее?

ответ

1

Вот запрос без CONVERT или СЛУЧАЙ:

SELECT * 
FROM HastaKurumlari 
WHERE '21-05-2009' between startDate and IsNull(endDate,getdate()) 

Чтобы убедиться, что Sql Server doens't оценить GETDATE() для каждой строки, вы можете кэшировать его, хотя я уверен, что Sql Server умный достаточно по умолчанию:

declare @now datetime 
set @now = getdate() 

SELECT * 
FROM HastaKurumlari 
WHERE '21-05-2009' between startDate and IsNull(endDate,@now) 

проводки план запроса может помочь объяснить, почему запрос медленно:

SET SHOWPLAN_TEXT ON 
go 
SELECT * 
FROM HastaKurumlari 
WHERE CONVERT(SMALLDATETIME,'21-05-2009',103) 
BETWEEN startDate 
    AND (CASE WHEN endDate IS NULL THEN GETDATE() ELSE endDate END) 
+0

Это проще, чем совместная функция и быстрее, чем раньше. Но coalesce также полезная функция. – uzay95

+0

Единственная разница между Coalesce и IsNUll заключается в том, что Coalesce может принимать более двух аргументов. Например, Coalesce (null, null, 3) вернет 3. – Andomar

+3

@Andomar: не совсем верно: семантика немного отличается, например. COALESCE продвигает к «наивысшему» типу данных, тогда как ISNULL использует первое найденное. Кроме того, COALESCE, являющийся стандартным SQL, более портативен. Кстати, я предпочитаю CURRENT_TIMESTAMP над getdate(). – onedaywhen

1

Вы можете попробовать функцию coalesce:

select * 
from HastaKurumlari 
where convert(smalldatetime, '21-05-2009', 103) 
    between startDate and coalesce(endDate, getdate()); 

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

+0

Второй не работает точно так же, как только указанная дата предшествует текущей дате, а endDate - null. Первый будет включать запись, а второй - опустить ее. – tvanfosson

+0

Ах, вы правы! Второй пример удален ... –

+0

Да, вы правы, и спасибо вам, Андрей за ваш ответ. – uzay95

1

Если это критическая производительность, то, возможно, просто не используйте null для открытой даты окончания - вместо этого используйте максимальное поддерживаемое время (например, много 9 секунд).

Я бы также сделать преобразование отдельно:

DECLARE @when datetime 
SET @when = CONVERT(SMALLDATETIME,'21-05-2009',103) 

SELECT * 
    FROM HastaKurumlari 
WHERE @when 
BETWEEN startDate AND endDate 

Существует еще кое-что немного отличается в выше и оригинал; если вы можете объяснить умысел проверки GETDATE() Возможно, я смогу аккуратно (читай: исправить) немного.

+0

Я думал, что SQL Server достаточно умен, чтобы заметить преобразование «в запросе» и делать это только один раз, до любого сканирования таблицы или индекса. –

+0

GETDATE() полезно установить endDate. Но если я запрошу прошлое, мне нужно будет установить endDate для того, когда или DateAdd (d, 1, @ When). Но этот запрос не может быть запущен. Потому что наш endDate по-прежнему NULL. – uzay95

+0

@ Андрю - мне легче сделать это явным; меньше вещей, чтобы помнить ... –

1

В качестве отправной точки воспользуйтесь GETDATE(), чтобы ее вызывали только один раз, и вы должны увидеть улучшение скорости.

Как вы его написали, вы просите GETDATE() оценивать каждый раз, когда enddate имеет значение NULL.

Поскольку функция GETDATE() является функцией non-deterministic, запрос не может быть оптимизирован и будет стремиться к выполнению.

+0

Просто сделал запрос, который использовал getdate() больше, чем строки milion, и это было так же быстро, как и тот, который использовал кешированную дату. – Andomar

+0

@Andomar опубликовать код, который вы использовали? –