Ограничение диапазона дат с точностью в MS SQL / SQL Server 2005 - PullRequest
1 голос
/ 05 января 2009

Я хочу ограничить отчет возвращением записей с даты 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 января до 23: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 апреля (ха! Запись April Fool! Grr), если использую в любое время позже 11:59:29. Почему это?

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

Ответы [ 5 ]

5 голосов
/ 05 января 2009

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

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
2 голосов
/ 05 января 2009

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

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

1 голос
/ 01 ноября 2010

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

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.

1 голос
/ 05 января 2009

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

Если ваша таблица использует datetime, попробуйте явно преобразовать значения @startDate и @endDate в значения DATETIME (CAST (@endDate AS DATETIME)).

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

У вас есть три варианта:

1) МЕЖДУ CAST ('01 / 01/2008 00: 00.000 'КАК DATETIME) И CAST ('03 / 31/2008 12: 59: 59.997' AS DATETIME)

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

3) my_date> = CAST ('01 / 01/2008 00: 00.000 'как дата) и my_date

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

0 голосов
/ 03 апреля 2013

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

Тогда сделайте запрос где юлианский> = '20120103' и юлианский <= '20120203' </p>

...