Ограничение диапазона дат с точностью в MS SQL / SQL Server 2005
-
03-07-2019 - |
Вопрос
Я хочу ограничить отчет возвратом записей с даты 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'