Подтвердить что ты не робот

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

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

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

Каков оптимальный, индексируемый способ выполнения примерно так:

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

Ответ 1

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

Если вы ищете лучший способ для дат, то ваш пример верен, но вы можете принять во внимание разницу точности 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'

Ответ 2

Лучший способ разделить временную часть поля datetime - использовать функции latiff и dateadd.

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

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

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

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

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

а не

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

* ПРИМЕЧАНИЕ. Внутренне второе целое (временная часть) хранит тики. Через день есть 24 x 60 X 60 X 300 = 25,920,000 тиков (пошагово, чуть ниже максимального значения, которое может содержать 32-битное целое число). Однако вам не нужно беспокоиться об этом при арифметическом изменении даты и времени... При добавлении или вычитании значений из datetimes вы можете рассматривать значение как дробь, как если бы оно было точно равно дробной части дня, как если бы полное значение datetime было числом с плавающей запятой, состоящим из целочисленной части, представляющей дату и дробную часть, представляющую время). т.е.

`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`

Ответ 3

Правильно - выполнение преобразования будет выполнять преобразование для каждой запрошенной строки. Лучше оставить столбцы даты в качестве дат и передать свои предложения в качестве дат:

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

Ответ 4

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