Преобразование SQL-сервер поля даты-время для сравнения только даты частей, с индексированными поисками

голоса
28

Я делал convert(varchar,datefield,112)на каждом поле даты , которые я использую в «между» запросов в сервере SQL , чтобы убедиться , что я только для учета дат и не пропуская ни на основе времени части даты и времени полей.

Теперь я слышу, что новообращенные не индексируемые и что есть более эффективные методы, в SQL Server 2005, для сравнения даты части DateTimes в запросе, чтобы определить, если даты попадают в диапазоне.

Что является оптимальным, индексируемых, способ сделать что-то вроде этого:

select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
Задан 09/12/2008 в 15:59
источник пользователем
На других языках...                            


5 ответов

голоса
65

Лучший способ лишить время часть поля даты и времени использует DATEDIFF и DATEADD функцию.

   DateAdd(day, datediff(day,0, MydateValue), 0)

Это занимает advantedge тот факт , что магазины SQL Server даты как два целых числа, одна из которых представляет число дней с первого дня «0» - (1 января 1900), а второй один , который представляет собой число тиков (каждый тик составляет около 3,33 мс ) с полуночи (по времени) *.

формула выше просто должен читать только первое целое число. Там нет преобразования или обработки требуется, поэтому он очень быстро.

Для того, чтобы сделать ваши запросы использовать индекс ... использовать эту формулу на фильтрации входных параметров первой, или на «другой» стороне знака равенства из временного поля даты таблицы, так что оптимизатор запросов не должен запустить расчет на каждое поле даты и время в таблице, чтобы определить, какие строки удовлетворяют предикат фильтра. Это делает ваш аргумент поиска «SARG-состояния» (Search аргумент)

Where MyDateTimeColumn > DateAdd(day, 
      datediff(day,0, @MydateParameter), 0)    -- SARG-able

скорее, чем

Where DateAdd(day, datediff(day,0, 
      MyDateTimeColumn ), 0) > @MydateParameter -- Not SARG-able

* ЗАМЕТКА. Внутренне, второе целое (время часть) хранит клещей. В день существует 24 х 60 х 60 х 300 = 25,920,000 клещи (интуитивно чуть ниже максимального значения 32-битное целое может содержать). Тем не менее, вам не нужно беспокоиться об этом, когда арифметически модификации DateTime ... При добавлении или вычитании значения из DateTimes можно рассматривать значение в виде дроби, как если бы она была в точности равна дробной части дня, как если бы полное значение даты и времени было число с плавающей точкой, состоящий из целой части, представляющей дату и дробную часть, представляющую время). т.е.

`Declare @Dt DateTime  Set @Dt = getdate()  
 Set @Dt = @Dt + 1.0/24  -- Adds one hour  
 Select @Dt  
 Set @Dt = @Dt - .25 -- Moves back 6 hours  
 Select @Dt`
Ответил 09/12/2008 в 16:07
источник пользователем

голоса
5

Преобразование числовых типов в строку значений (тип бокса) не лучший способ выполнения делать то, что вы ищете. Его на самом деле не о состоянии индекса, так как фактический тип столбца даты и времени.

Если вы ищете лучший способ запроса для дат, то ваш пример является правильным, но вы можете принять во внимание разницу в 3 мс точность в MSSQL. Это может означать, что записи с одного дня могут появиться в результате другого дня.

Эта

select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'

Должно быть это

select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<='08-14-2008 23:59:59.996'
Ответил 09/12/2008 в 16:11
источник пользователем

голоса
2

Это правильно - делать преобразование будет выполнять преобразование для каждой строки запрошены. Это лучше оставить столбцы даты как даты, и передать в своем ИНЕК как даты:

select * from appointments where appointmentdate between 
'08/01/2008' AND '08/16/2008'

Примечание: Выход от времени означает полночь (00: 00.000), так что вы будете включать в себя все времена для 08/01, и все время от 08/15, и ничего, что именно 08/16/2008 00:00:00

Ответил 09/12/2008 в 16:06
источник пользователем

голоса
1

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

Ответил 09/12/2008 в 16:10
источник пользователем

голоса
0

Существует также способ описан в http://www.stillnetstudios.com/comparing-dates-without-times-in-sql-server/

SELECT CAST(FLOOR(CAST( getdate() AS float )) AS datetime)
Ответил 28/09/2011 в 13:31
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more