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

MS SQL Date Only Without Time

Вопрос

Привет всем,

У меня была некоторая путаница в течение довольно долгого времени, в основном, настил типа DateTime SQL с использованием T-SQL. По сути, я хочу взять значение DateTime, например, 2008-12-1 14:30:12 и сделать это 2008-12-1 00:00:00. В запросах, которые мы запускаем для отчетов, используется значение даты в предложении WHERE, но у меня либо есть значение даты начала и окончания дня, либо использование BETWEEN или я нахожу какой-то другой метод.

В настоящее время я использую следующее: WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam

Однако это кажется довольно неуклюжим. Я надеялся, что будет что-то более простое, как CAST([tstamp] AS DATE)

Некоторые места в Интернете рекомендуют использовать функцию DATEPART(), но потом я получаю что-то вроде этого:


WHERE DATEPART(year, [tstamp]) = DATEPART(year, @dateParam)
AND DATEPART(month, [tstamp]) = DATEPART(month, @dateParam)
AND DATEPART(day, [tstamp]) = DATEPART(day, @dateParam)

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

Любые предложения?

Спасибо,
С

Решение

Спасибо всем за отличную обратную связь. Много полезной информации. Я собираюсь изменить наши функции, чтобы устранить функцию в левой части оператора. Хотя большинство наших столбцов даты не используют индексы, вероятно, это еще лучше.

4b9b3361

Ответ 1

что очень плохо для производительности, посмотрите Только в базе данных вы можете получить 1000% + улучшение, меняя несколько строк кода

функции в левой части оператора плохие

вот что вам нужно сделать

declare @d datetime
select @d =  '2008-12-1 14:30:12'

where tstamp >= dateadd(dd, datediff(dd, 0, @d)+0, 0)
and tstamp < dateadd(dd, datediff(dd, 0, @d)+1, 0)

Запустите это, чтобы посмотреть, что он делает

select dateadd(dd, datediff(dd, 0, getdate())+1, 0)
select dateadd(dd, datediff(dd, 0, getdate())+0, 0)

Ответ 2

Если вы используете SQL Server 2008, он теперь встроен в это, см. это в книги онлайн

CAST(GETDATE() AS date)

Ответ 3

Функции Date, отправленные другими, являются наиболее правильным способом справиться с этим.

Однако смешно упоминать термин "пол", потому что там немного взломать, который будет работать несколько быстрее:

CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime)

Ответ 4

CONVERT(date, GETDATE()) и CONVERT(time, GETDATE()) работает в SQL Server 2008. Я не уверен в 2005 году.

Ответ 5

Как насчет этого?

SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0)

Ответ 6

DATEADD(d, 0, DATEDIFF(d, 0, [tstamp]))

Изменить: в то время как это удалит временную часть вашего datetime, она также сделает условие non SARGable. Если это важно для этого запроса, более подходящим является индексный просмотр или предложение inter.

Ответ 7

Да, T-SQL может время от времени чувствовать себя чрезвычайно примитивным, и именно такие вещи часто меня заставляют делать большую часть моей логики на моем языке выбора (например, С#).

Однако, когда вам абсолютно необходимо выполнять некоторые из этих действий в SQL по соображениям производительности, лучше всего создать функции для размещения этих "алгоритмов".

Взгляните на эту статью. Он предлагает довольно много удобных функций SQL в этих строках, которые, я думаю, помогут вам.

http://weblogs.sqlteam.com/jeffs/archive/2007/01/02/56079.aspx

Ответ 8

Осторожно, если вы используете что-то длинное, строки WHERE CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam, это заставит сканирование в таблице, и никакие индексы не будут использоваться для этой части.

Более чистый способ сделать это - определить вычисляемый столбец

create table #t (
    d datetime, 

    d2 as 
        cast (datepart(year,d) as varchar(4)) + '-' +
        right('0' + cast (datepart(month,d) as varchar(2)),2) + '-' + 
        right('0' + cast (datepart(day,d) as varchar(2)),2) 
) 
-- notice a lot of care need to be taken to ensure the format is comparable. (zero padding)

insert #t 
values (getdate())

create index idx on #t(d2)

select d2, count(d2) from #t 
where d2 between '2008-01-01' and '2009-01-22'
group by d2
-- index seek is used

Таким образом, вы можете напрямую проверить столбец d2, и будет использоваться индекс, и вам не придется гадать с конверсиями.

Ответ 9

Здесь запрос, который вернет все результаты в течение нескольких дней.

DECLARE @startDate DATETIME
DECLARE @endDate DATETIME

SET @startDate = DATEADD(day, -30, GETDATE())
SET @endDate = GETDATE()

SELECT *
FROM table
WHERE dateColumn >= DATEADD(day, DATEDIFF(day, 0, @startDate), 0)
  AND dateColumn <  DATEADD(day, 1, DATEDIFF(day, 0, @endDate))

Ответ 10

FWIW, я делал то же самое, что и вы годами

CAST(CONVERT(VARCHAR, [tstamp], 102) AS DATETIME) = @dateParam 

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

Ответ 11

В качестве альтернативы вы можете использовать

declare @d datetimeselect
@d =  '2008-12-1 14:30:12'
where tstamp 
  BETWEEN dateadd(dd, datediff(dd, 0, @d)+0, 0) 
  AND dateadd(dd, datediff(dd, 0, @d)+1, 0)

Ответ 12

WHERE DATEDIFF(day, tstamp, @dateParam) = 0

Это должно привести вас туда, если вам не нужно время.

Это ответ на мета-вопрос о сравнении дат двух значений, когда вы не заботитесь о времени.