MS SQL Дата только без времени - PullRequest
38 голосов
/ 22 января 2009

Вопрос

Привет всем,

В течение довольно долгого времени у меня возникала путаница, когда я по существу определял тип SQL DateTime с использованием 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)

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

Есть предложения?

Спасибо,
С

Решение

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

Ответы [ 12 ]

79 голосов
/ 22 января 2009

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

CAST(GETDATE() AS date)

35 голосов
/ 22 января 2009

, что очень плохо для производительности, посмотрите на Только в базе данных вы можете получить улучшение на 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)
9 голосов
/ 22 января 2009

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

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

CAST(FLOOR(CAST(@dateParam AS float)) AS DateTime)
7 голосов
/ 09 ноября 2009

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

5 голосов
/ 06 июня 2011

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

SELECT DATEADD(dd, DATEDIFF(dd,0,GETDATE()), 0)
1 голос
/ 22 января 2009

Осторожно, если вы используете что-либо, длинное из строк 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 и использовать индекс, и вам не придётся возиться с конверсиями.

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

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

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

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

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

1 голос
/ 22 января 2009
DATEADD(d, 0, DATEDIFF(d, 0, [tstamp]))

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

0 голосов
/ 19 ноября 2009

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

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)
0 голосов
/ 22 января 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...