Лучший подход для удаления части времени datetime в SQL Server - PullRequest
499 голосов
/ 24 июля 2009

Какой метод обеспечивает наилучшую производительность при удалении части времени из поля даты и времени в SQL Server?

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

или

b) select cast(convert(char(11), getdate(), 113) as datetime)

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

Оба также выглядят очень быстрыми, но может быть разница в скорости при работе с сотнями тысяч или более строк?

Кроме того, возможно ли, что есть еще лучшие способы избавиться от части времени datetime в SQL?

Ответы [ 23 ]

537 голосов
/ 24 июля 2009

Строго говоря, метод a является наименее ресурсоемким:

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

Доказано, что процессор менее загружен при той же общей продолжительности миллион строк кем-то, у кого слишком много времени: Самый эффективный способ в SQL Server получить дату от даты + время?

Я видел аналогичный тест в другом месте с аналогичными результатами.

Я предпочитаю DATEADD / DATEDIFF, потому что:

  • varchar подвержен проблемам с языковым форматом / форматом даты
    Пример: Почему мое выражение CASE недетерминировано?
  • float зависит от внутреннего хранилища
  • он распространяется на первый день месяца, завтра и т. Д., Изменяя базовую «0»

Редактировать, октябрь 2011

Для SQL Server 2008+, вы можете CAST к date. Или просто используйте date, чтобы не было времени удалить.

Редактировать, январь 2012

Рабочий пример того, насколько это гибко: Необходимо рассчитать поокругленное значение времени или даты на сервере sql

Edit, May 2012

Не используйте это в предложениях WHERE и т. п., не задумываясь: добавляя функцию илиCAST к столбцу делает недействительным использование индекса. Смотрите номер 2 здесь: http://www.simple -talk.com / sql / t-sql-программирование / десять-общих-sql-программирование-ошибок /

Теперь у этого есть примерболее поздние версии оптимизатора SQL Server, управляющие CAST, корректно обновляются, но обычно будет плохой идеей ...

Редактировать, сентябрь 2018 г., для datetime2

DECLARE @datetime2value datetime2 = '02180912 11:45' --this is deliberately within datetime2, year 0218
DECLARE @datetime2epoch datetime2 = '19000101'

select DATEADD(dd, DATEDIFF(dd, @datetime2epoch, @datetime2value), @datetime2epoch)
62 голосов
/ 23 октября 2013

В SQL Server 2008 вы можете использовать:

CONVERT(DATE, getdate(), 101)
46 голосов
/ 04 мая 2012

Конечно, это старый поток, но для его завершения.

В SQL 2008 вы можете использовать тип данных DATE, поэтому вы можете просто:

SELECT CONVERT(DATE,GETDATE())
21 голосов
/ 24 июля 2009
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)

... это не хорошее решение, согласно комментариям ниже.

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

16 голосов
/ 04 апреля 2014

В SQL Server 2008 существует тип даты DATE (также тип данных TIME).

CAST(GetDate() as DATE)

или

declare @Dt as DATE = GetDate()
8 голосов
/ 24 июля 2009

Вот еще один ответ из другого дублирующего вопроса:

SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime) 

Этот метод с магическим числом работает немного быстрее, чем метод DATEADD. (Похоже, ~ 10%)

Процессорное время на нескольких раундах миллиона записей:

DATEADD   MAGIC FLOAT
500       453
453       360
375       375
406       360

Но обратите внимание, что эти числа, возможно, не имеют значения, потому что они уже ОЧЕНЬ быстрые. Если бы у меня не было наборов записей 100 000 или более, я бы даже не смог прочитать процессорное время выше нуля.

Учитывая тот факт, что DateAdd предназначен для этой цели и является более надежным, я бы сказал, использоватьDateAdd.

5 голосов
/ 03 июля 2013
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)
5 голосов
/ 10 января 2017

Мне действительно нравится:

[date] = CONVERT(VARCHAR(10), GETDATE(), 120)

Код формата 120 приведёт дату в стандарт ISO 8601:

'YYYY-MM-DD' or '2017-01-09'

Очень прост в использовании в dplyr (R) и панды (Python)!

3 голосов
/ 20 января 2014

ВНИМАНИЕ!

Метод a) и b) НЕ всегда имеют одинаковый вывод!

select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0)

Вывод: 2014-01-01 00:00:00.000

select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime)

Вывод:2013-12-31 00:00:00.000

(протестировано на MS SQL Server 2005 и 2008 R2)

РЕДАКТИРОВАТЬ: Согласно комментарию Адама, это не может произойти, если вы читаете значение даты из таблицы, но это может произойтиесли вы указали значение даты в виде литерала (например, в качестве параметра хранимой процедуры, вызываемой через ADO.NET).

2 голосов
/ 18 ноября 2011
CAST(round(cast(getdate()as real),0,1) AS datetime)

Этот метод не использует строковую функцию. Date - это, в основном, настоящий тип данных с цифрами перед десятичной дробью, составляющей часть дня.

Я думаю, это будет быстрее, чем много.

...