Какой метод обеспечивает наилучшую производительность при удалении части времени из поля даты и времени в SQL Server?
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
или
b) select cast(convert(char(11), getdate(), 113) as datetime)
Второй способ отправляет еще несколько байтов в любом случае, но это может быть не так важно, как скорость преобразования.
Оба также кажутся очень быстрыми, но может быть разница в скорости при работе с сотнями тысяч или более строк?
Кроме того, возможно ли, что есть еще лучшие методы, чтобы избавиться от части времени datetime в SQL?
Ответы:
Строго говоря, метод
a
является наименее ресурсоемким:Доказано, что процессор требует меньше ресурсов при той же общей продолжительности - миллион строк, причем слишком много времени у них на руках: самый эффективный способ в SQL Server получить дату от даты + время?
Я видел аналогичный тест в другом месте с аналогичными результатами тоже.
Я предпочитаю DATEADD / DATEDIFF, потому что:
Пример: почему мое выражение CASE недетерминировано?
Редактировать, октябрь 2011
Для SQL Server 2008+, можно заливать в
date
то естьCAST(getdate() AS date)
. Или просто используйтеdate
тип данных, поэтому нет времени, чтобы удалить.Редактировать, январь 2012
Работающий пример того, насколько это гибко: нужно рассчитать по округленному времени или дате в SQL Server
Редактировать, май 2012
Не используйте это в предложениях WHERE и тому подобном, не задумываясь: добавление функции или CAST к столбцу делает недействительным использование индекса. Смотрите номер 2 здесь: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/
Теперь есть пример более поздних версий оптимизатора SQL Server, которые корректно управляют CAST, но в целом это будет плохая идея ...
Изменить, сентябрь 2018 года, для datetime2
источник
DATE
данных неприятно ограничивает то, что оно позволяет вам делать в отношении таких вещей, как dateadd, datediff и взаимодействие с другими типами данных даты / времени. Для этих случаевDATEADD()
подход царя царя.0218
вместо2018
года год, иDATEDIFF
часть вашего утверждения выдает исключение.The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime value
Попробуйте:select DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
SELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
В SQL Server 2008 вы можете использовать:
источник
datetime
в adate
, поэтому ваше решение фактически сводится к справедливомуCONVERT(DATE,getdate())
, что уже предлагалось не раз.CAST(GETDATE() AS DATE)
или строго ANSI,CAST(CURRENT_TIMESTAMP AS DATE)
который я считаю бесполезным. Оставайтесь с первым.Конечно, это старая тема, но для ее завершения.
Начиная с SQL 2008, вы можете использовать тип данных DATE, так что вы можете просто сделать:
источник
... не очень хорошее решение, согласно комментариям ниже.
Я бы удалил этот ответ, но оставлю его здесь в качестве контрпримера, так как думаю, что объяснение комментаторов, почему это не очень хорошая идея, все еще полезно.
источник
В SQL Server 2008 существует тип даты DATE (также тип данных TIME).
или
источник
Вот еще один ответ из другого дублирующего вопроса:
Этот метод магического числа работает немного быстрее, чем метод DATEADD. (Похоже, ~ 10%)
Время процессора на несколько раундов из миллиона записей:
Но обратите внимание, что эти цифры, возможно, не имеют значения, потому что они уже очень быстро. Если бы у меня не было наборов записей 100 000 и более, я бы даже не смог получить процессорное время для чтения выше нуля.
Учитывая тот факт, что DateAdd предназначен для этой цели и является более надежным, я бы сказал, использовать DateAdd.
источник
'12:00:00.003'
что я считаю гораздо лучше.источник
Мне действительно нравится:
Код
120
формата приведёт дату в стандарт ISO 8601:Супер прост в использовании в dplyr (
R
) и pandas (Python
)!источник
BEWARE!
Метод а) и б) НЕ всегда имеют одинаковый результат!
Вывод:
2014-01-01 00:00:00.000
Вывод:
2013-12-31 00:00:00.000
(Проверено на MS SQL Server 2005 и 2008 R2)
РЕДАКТИРОВАТЬ: Согласно комментарию Адама, это не может произойти, если вы читаете значение даты из таблицы, но это может произойти, если вы укажите свое значение даты в виде литерала (пример: в качестве параметра хранимой процедуры, вызываемой через ADO.NET).
источник
DATETIME
столбце. Максимально возможное значение - 0,999. От: msdn.microsoft.com/en-us/library/ms187819.aspx вы увидите, что значения округлены до тысячного места до 0, 3 или 7. OP не увидит значение из вашего теста в их таблицах.Обрезать время на вставках / обновлениях в первую очередь. Что касается преобразования на лету, ничто не может превзойти определяемую пользователем функцию:
Реализация
date_only
может быть чем угодно - теперь она абстрагирована, а вызов кода намного чище.источник
WHERE DateAdd(DateDiff(Column)) = @DateValue
не будет использовать индекс. С другой стороны,WHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1)
это SARGable. Так что будьте осторожны, как вы это выразите.Смотрите этот вопрос:
Как я могу усечь дату и время в SQL Server?
Что бы вы ни делали, не используйте строковый метод . Это о худшем способе, которым ты мог сделать это.
источник
Уже ответили, но я тоже выбрасываю это там ... это также хорошо преформируется, но работает, отбрасывая десятичное число (которое хранит время) из числа с плавающей запятой и возвращая только целую часть (которая является датой)
во второй раз я нашел это решение ... я взял этот код
источник
Этот метод не использует строковую функцию.
Date
в основном настоящий тип данных с цифрами перед десятичной дробью являются частью дня.Я думаю, это будет быстрее, чем много.
источник
Для меня код ниже всегда победитель:
источник
выберите CONVERT (char (10), GetDate (), 126)
источник
Я думаю ты имеешь ввиду
cast(floor(cast(getdate()as float))as datetime)
real только 32-битный, и может потерять некоторую информацию
Это самый быстрый
cast(cast(getdate()+x-0.5 as int)as datetime)
... хотя только на 10% быстрее
(about 0.49 microseconds CPU vs. 0.58)
Это было рекомендовано, и сейчас у меня столько же времени в моем тесте:
DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
В SQL 2008 функция SQL CLR примерно в 5 раз быстрее, чем при использовании функции SQL, на 1,35 мкс по сравнению с 6,5 микросекциями, что указывает на гораздо меньшую нагрузку при вызове функции для функции SQL CLR по сравнению с простой UDF SQL.
В моем тесте SQL 2005 функция SQL CLR была в 16 раз быстрее, чем эта медленная функция:
источник
Как насчет
select cast(cast my_datetime_field as date) as datetime)
? Это приводит к одной и той же дате со временем, установленным на 00:00, но позволяет избежать преобразования в текст, а также избежать явного округления чисел.источник
Я думаю, что если строго придерживаться
TSQL
этого, это самый быстрый способ обрезать время:Я обнаружил, что этот метод усечения примерно на 5% быстрее, чем
DateAdd
метод. И это можно легко изменить, чтобы округлить до ближайшего дня, как это:источник
Здесь я сделал функцию для удаления некоторых частей datetime для SQL Server. Применение:
create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end
источник
На всякий случай, если кто-то ищет здесь версию Sybase, так как некоторые из вышеуказанных версий не работали
источник
cast
: для SQL Server 2008+ вы можете использовать CAST на сегодняшний день. Или просто используйте дату, поэтому нет времени, чтобы удалить.datetime
вdate
: ни один из них не имеет встроенного формата.Если возможно, для особых вещей, подобных этому, мне нравится использовать функции CLR.
В этом случае:
источник
Лично я почти всегда пользуюсь пользовательские функции для этого, если имеешь дело с SQL Server 2005 (или более ранней версией), однако следует отметить, что существуют определенные недостатки использования UDF, особенно если применять их к предложениям WHERE (см. Ниже и комментарии к этому ответу для получения дополнительной информации). Если используется SQL Server 2008 (или выше) - см. Ниже.
Фактически, для большинства баз данных, которые я создаю, я добавляю эти UDF в самом начале, так как знаю, что есть вероятность, что они мне понадобятся на 99% раньше или позже.
Я создаю один для «только дата» и «только время» (хотя один «только дата», безусловно, наиболее часто используемых из двух).
Вот несколько ссылок на различные датные UDF:
Основные функции SQL Server Date, Time и DateTime Функция
Get Only Only
Эта последняя ссылка показывает не менее 3 различных способов получения только даты в поле даты и времени и упоминает некоторые плюсы и минусы каждого подхода.
При использовании UDF следует отметить, что вы должны стараться избегать использования UDF как части предложения WHERE в запросе, так как это сильно снизит производительность запроса. Основная причина этого заключается в том, что использование UDF в предложении WHERE делает это предложение несортируемым , что означает, что SQL Server больше не может использовать индекс с этим предложением для повышения скорости выполнения запроса. Что касается моего собственного использования UDF, я часто буду использовать «необработанный» столбец даты в предложении WHERE, но применяю UDF к столбцу SELECTed. Таким образом, UDF применяется только к отфильтрованному набору результатов, а не к каждой строке таблицы как части фильтра.
Конечно, абсолютно лучший подход для этого - использовать SQL Server 2008 (или выше) и разделять ваши даты и время , так как ядро базы данных SQL Server изначально предоставляет отдельные компоненты даты и времени и может эффективно запрашивать их независимо без необходимости использования UDF или другого механизма для извлечения части даты или времени из составного типа дата-время.
источник
WHERE DateColumn >= {TimeTruncatingExpression}(@DateValue) AND DateColumn < {TimeTruncatingExpression}(@DateValue + 1)
. Я чувствовал, что должен был что-то сказать, поскольку вы сказали, что «я почти всегда использую UDF», не объяснили ни недостатков, ни способа сделать запрос на дату только SARGable.Я хотел бы использовать:
Таким образом, эффективно создавая новое поле из поля даты, которое у вас уже есть.
источник
datetime
значения, преобразовать их в строки, объединить их вместе и, наконец, преобразовать результат обратно,datetime
лучше, чем, например, выполнить прямые вычисления для оригиналаdatetime
( методDATEADD
/DATEDIFF
)?MM
иDD
? В SQL Server нет таких функций.