Ограничение диапазона дат с точностью в MS SQL / SQL Server 2005

StackOverflow https://stackoverflow.com/questions/414276

Вопрос

Я хочу ограничить отчет возвратом записей с даты A по дату B.Это то, что я делал:

declare @startDate varchar(20)
declare @endDate varchar(20)
set @startDate = '01/01/2008'
set @endDate = '04/01/2008'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections 
where date between @startDate and @endDate

...который, как мне сказали, вернул записи с 12 часов утра 1 января по 11: 59 вечера 31 марта (по умолчанию используется полночь, когда время не указано).Но я заметил несоответствие, которое заключается в том, что если время записи равно 00:00: 00, то она будет частью этого набора.

Есть ли более точный способ сделать это, чтобы он возвращал именно тот диапазон дат, который я хочу?*

Я пытался использовать время:

declare @startDate varchar(20)
declare @endDate varchar(20)
set @startDate = '01/01/2008 00:00:00'
set @endDate = '04/01/2008 11:59:59'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections 
where date between @startDate and @endDate

...но я заметил кое-что шаткое:SQL Server ОКРУГЛИТ сотую секунду вдвое.Итак, я получаю эту запись от 1 апреля (ха!Первоапрельский рекорд дурака!grr) если я использую любое время позже 11:59:29.Почему это?

  • (Я уверен, что так оно и есть.Я новичок в этом.Спасибо за вашу помощь!)
Это было полезно?

Решение

Всегда есть простой вариант:

declare @startDate varchar(20)
declare @endDate varchar(20)
set @startDate = '01/01/2008'
set @endDate = '04/01/2008'

-- test what are the start and end dates
select min(date),max(date) from view_Inspections 
where date >= @startDate 
and   date < @endDate

Другие советы

Я подозреваю, что столбец даты в view_Inspections является типом данных SmallDateTime.Этот тип данных имеет точность в 1 минуту, что объясняет ваши неожиданные результаты (округление секунд до ближайшей минуты).

Метод, предложенный Роландом Шоу, - это лучший способ изменить ваш запрос в соответствии с вашими требованиями.

Оператор BETWEEN является инклюзивным, именно поэтому вы видите результаты, которые вы получили в своем первом запросе.Округление, которое вы видите во втором запросе, будет зависеть от того, какой точный тип данных datetime вы используете в своей таблице.(Кстати, я думаю, вы путаете секунды с сотыми долями секунды).Похоже, вы, вероятно, используете smalldatetime в своей таблице, и в этом случае время округляется до ближайшей минуты.

Если ваша таблица использует datetime, попробуйте явно преобразовать ваши значения @StartDate и @EndDate в DATETIME (ПРИВЕДИТЕ(@EndDate КАК DATETIME)).

Краткое замечание...даже для значений DATETIME SQL Server работает с точностью всего до 3/100 секунды, поэтому 11:59:59.999 будет округлено до 12:00:00.000.

В принципе, у вас есть три варианта:

1) МЕЖДУ ПРИВЕДЕНИЕМ ('01/01/2008 00:00:00.000' В КАЧЕСТВЕ ДАТЫ-ВРЕМЕНИ) И ПРИВЕДЕНИЕМ ('31.03.2008 12:59:59.997' В КАЧЕСТВЕ ДАТЫ-ВРЕМЕНИ)

2) ГОД (my_date) = 2008 И МЕСЯЦ (my_date) МЕЖДУ 1 И 3

3) my_date >= ПРИВЕДЕНИЕ ('01/01/2008 00:00:00.000' В КАЧЕСТВЕ ДАТЫ-ВРЕМЕНИ) И my_date < АКТЕРСКИЙ СОСТАВ ('01.04.2008 00:00:00.000' В КАЧЕСТВЕ ДАТЫ И ВРЕМЕНИ)

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

Просто попробуйте удалить время из поля даты следующим образом:

declare @startDate varchar(20)
declare @endDate varchar(20)
set @startDate = '01/01/2008'
set @endDate = '04/01/2008'

SELECT min(date),max(date) FROM view_Inspections 
WHERE CAST(FLOOR(CAST(date AS FLOAT)) AS DATETIME) BETWEEN CAST(@startDate AS DATETIME) And CAST(@startDate AS DATETIME))

Это вернет все из 01/01/2008 00:00:00 Для 04/01/2008 11:59:59.999.Если ты не хочешь 04/01 включено, измените дату окончания на 03/31/2008.

Ваше лучшее решение - просто создать поле BIGINT (10) с именем "julian" и сохранить его в YYYYMMDD.

Затем выполните запрос где julian >= '20120103' И julian <= '20120203'

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top