Каков наилучший способ усечения значения datetime (как удалить часы минут и секунд) в SQL Server 2008?
Например:
declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)
-----------------------
2009-05-28 00:00:00.000
Каков наилучший способ усечения значения datetime (как удалить часы минут и секунд) в SQL Server 2008?
Например:
declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)
-----------------------
2009-05-28 00:00:00.000
Это продолжает часто собирать дополнительные голоса, даже несколько лет спустя, поэтому мне нужно обновить его для современных версий Sql Server. Для Sql Server 2008 и более поздних версий это просто:
cast(getDate() As Date)
Обратите внимание, что последние три абзаца рядом с дном все еще применяются, и вам часто нужно сделать шаг назад и найти способ избежать броска в первую очередь.
Но есть и другие способы сделать это. Здесь наиболее распространены.
Правильный способ (новый с Sql Server 2008):
cast(getDate() As Date)
Правильный способ (старый):
dateadd(dd, datediff(dd,0, getDate()), 0)
Это уже сейчас, но все же стоит знать, потому что он также может легко адаптироваться к другим моментам времени, таким как первый момент месяца, минуты, часа или года.
Этот правильный способ использует документированные функции, которые являются частью стандарта ansi и гарантированно работает, но может быть несколько медленнее. Это работает, когда вы обнаруживаете, сколько дней прошло с 0-го дня до текущего дня, и добавив, что много дней назад до дня 0. Он будет работать независимо от того, как хранится ваше дата-время и независимо от того, какой у вас язык.
Быстрый способ:
cast(floor(cast(getdate() as float)) as datetime)
Это работает, потому что столбцы datetime хранятся как 8-байтовые двоичные значения. Бросьте их, чтобы поплавать, поместите их, чтобы удалить фракцию, и временная часть значений исчезнет, когда вы вернете их обратно в datetime. Все это просто смещается без сложной логики, и это очень быстро.
Помните, что это зависит от детали реализации, которую Microsoft может изменять в любое время, даже в автоматическом обновлении службы. Это также не очень портативно. На практике очень маловероятно, что эта реализация изменится в ближайшее время, но все же важно знать об опасности, если вы решите ее использовать. И теперь, когда у нас есть возможность использовать дату, она редко необходима.
Неверный путь:
cast(convert(char(11), getdate(), 113) as datetime)
Неправильный способ работает путем преобразования в строку, обрезания строки и преобразования в datetime. Это неправильно, по двум причинам: 1) он может не работать во всех локалях и 2) он о самом медленном возможном способе сделать это... и не просто немного; он как на порядок или два медленнее, чем другие варианты.
Обновление. В последнее время это дает некоторые голоса, поэтому я хочу добавить к нему, что, поскольку я опубликовал это, я видел довольно убедительные доказательства того, что Sql Server оптимизирует разницу в производительности между "правильный" способ и "быстрый" способ, то есть вы должны теперь одобрить первое.
В любом случае вы хотите написать свои запросы, чтобы избежать необходимости делать это в первую очередь. Очень редко вы должны делать эту работу в базе данных.
В большинстве мест база данных уже является вашим узким местом. Как правило, сервер, который является самым дорогим для добавления оборудования для повышения производительности, и самый жесткий для правильного добавления этих дополнений (например, для балансировки дисков с памятью). Это также труднее всего масштабировать наружу, как технически, так и с коммерческой точки зрения; гораздо проще технически добавить веб-сервер или сервер приложений, чем сервер базы данных, и даже если это было неверно, вы не платите 20 000 долларов США за серверную лицензию для IIS или apache.
То, что я пытаюсь сделать, это то, что, когда это возможно, вы должны делать эту работу на уровне приложения. Единственный раз, когда вы когда-либо находите, что вы усекаете дату и время на сервере Sql, - это когда вам нужно группировать по дням, и даже тогда вы, вероятно, должны иметь дополнительный столбец, настроенный как вычисленный столбец, поддерживаемый во время вставки/обновления или поддерживаемый в прикладной логике. Получите эту индексную, тяжелую работу с вашей базой данных.
Только для SQL Server 2008
CAST(@SomeDateTime AS Date)
Затем верните его в datetime, если хотите
CAST(CAST(@SomeDateTime AS Date) As datetime)
Только для более полного ответа, здесь рабочий путь для усечения любой из частей даты вниз и включая минуты (замените GETDATE()
на дату усечения).
Это отличается от принятого ответа тем, что вы можете использовать не только dd
(дни), но и любую из частей даты (см. здесь):
dateadd(minute, datediff(minute, 0, GETDATE()), 0)
Обратите внимание, что в приведенном выше выражении 0
является постоянной датой начала года (1900-01-01). Если вам нужно усечь на более мелкие части, например, на секунды или миллисекунды, вам нужно принять постоянную дату, которая ближе к дате, которая будет усечена, чтобы избежать переполнения.
Фрагмент, который я нашел в Интернете, когда мне нужно было это сделать:
dateadd(dd,0, datediff(dd,0, YOURDATE))
e.g.
dateadd(dd,0, datediff(dd,0, getDate()))
В SQl 2005 ваша функция trunc_date может быть записана следующим образом.
(1)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
CAST(FLOOR( CAST( @date AS FLOAT ) )AS DATETIME)
END
Первый метод намного чище. Он использует только 3 вызова метода, включая окончательный CAST(), и не выполняет конкатенации строк, что является автоматическим плюсом. Кроме того, здесь нет огромных типов бросков. Если вы можете себе представить, что метки даты/времени могут быть представлены, то преобразование из дат в числа и обратно в даты является довольно простым процессом.
(2)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CONVERT(varchar, @date,112)
END
Если вы беспокоитесь о том, что реализация Microsoft datetimes (2) или (3) может быть в порядке.
(3)
CREATE FUNCTION trunc_date(@date DATETIME)
RETURNS DATETIME
AS
BEGIN
SELECT CAST((STR( YEAR( @date ) ) + '/' +STR( MONTH( @date ) ) + '/' +STR( DAY(@date ) )
) AS DATETIME
END
В-третьих, более подробный метод. Это требует разбивки даты на его год, месяц и день, соединяя их в формате "yyyy/mm/dd", а затем отбрасывая это на дату. Этот метод включает в себя 7 вызовов методов, включая окончательный CAST(), не говоря уже о конкатенации строк.
CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP)
вы могли бы просто сделать это (SQL 2008):
объявить @SomeDate date = getdate()
select @SomeDate
2009-05-28
Для тех из вас, кто пришел сюда, ища способ усечения поля DATETIME на что-то меньшее, чем целый день, например каждую минуту, вы можете использовать это:
SELECT CAST(FLOOR(CAST(GETDATE() AS FLOAT)) + (FLOOR((CAST(GETDATE() AS FLOAT) - FLOOR(CAST(GETDATE() AS FLOAT))) * 1440.0) + (3.0/86400000.0)) / 1440.0 AS DATETIME)
так что если сегодня было 2010-11-26 14:54:43.123
, тогда это вернет 2010-11-26 14:54:00.000
.
Чтобы изменить интервал, который он совершает, замените 1440.0 на количество интервалов в день, например:
24hrs = 24.0 (for every hour)
24hrs / 0.5hrs = 48.0 (for every half hour)
24hrs / (1/60) = 1440.0 (for every minute)
(Всегда помещайте a .0
на конец, чтобы неявно приводить к float.)
Для тех из вас, кто задается вопросом о том, что такое (3.0/86400000)
для моих вычислений, SQL Server 2005, похоже, не отличается от FLOAT
до DATETIME
, поэтому это добавляет 3 миллисекунды до его постинга.
выберите cast (floor (cast (getdate() как float)) как datetime) Ссылка на это: http://microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in-sql-server.html
Этот запрос должен предоставить результат, эквивалентный trunc(sysdate)
в Oracle.
SELECT *
FROM your_table
WHERE CONVERT(varchar(12), your_column_name, 101)
= CONVERT(varchar(12), GETDATE(), 101)
Надеюсь, это поможет!
Вы также можете извлечь дату using Substring
из переменной datetime, а возврат к datetime будет игнорировать временную часть.
declare @SomeDate datetime = '2009-05-28 16:30:22'
SELECT cast(substring(convert(varchar(12),@SomeDate,111),0,12) as Datetime)
Кроме того, вы можете получить доступ к частям переменной datetime и объединить их с укороченной датой конструкции, примерно так:
SELECT cast(DATENAME(year, @Somedate) + '-' +
Convert(varchar(2),DATEPART(month, @Somedate)) + '-' +
DATENAME(day, @Somedate)
as datetime)
Oracle:
TRUNC(SYSDATE, 'MONTH')
SQL Server:
DATEADD(DAY, - DATEPART(DAY, DateField) + 1, DateField)
Аналогичным образом можно использовать для усечения минут или часов с даты.
TRUNC (aDate, 'DD') усекает min, sec и hrs
SRC: http://www.techonthenet.com/oracle/functions/trunc_date.php