Как я могу усечь дату и время в SQL Server? - PullRequest
256 голосов
/ 29 мая 2009

Как лучше всего усекать значение даты и времени (чтобы удалить часы, минуты и секунды) в SQL Server 2008?

Например:

declare @SomeDate datetime = '2009-05-28 16:30:22'
select trunc_date(@SomeDate)

-----------------------
2009-05-28 00:00:00.000

Ответы [ 13 ]

459 голосов
/ 29 мая 2009

Это продолжает часто собирать дополнительные голоса, даже спустя несколько лет, и поэтому мне нужно обновить его для современных версий 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)

Это работает, потому что столбцы даты и времени хранятся как 8-байтовые двоичные значения. Приведите их к плавающему, напишите их, чтобы удалить дробь, и временная часть значений исчезнет, ​​когда вы вернете их назад к datetime. Это просто немного смещается без сложной логики, и это очень быстро.

Помните, что это зависит от деталей реализации, которые Microsoft может изменить в любое время, даже при автоматическом обновлении службы. Это также не очень портативный. На практике очень маловероятно, что эта реализация изменится в ближайшее время, но все же важно осознавать опасность, если вы решите ее использовать. И теперь, когда у нас есть возможность использовать дату, это редко требуется.

Неправильный путь:

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

Неправильный способ работает путем преобразования в строку, усечения строки и преобразования обратно в дату-время. Это неправильно по двум причинам: 1) он может работать не во всех локалях и 2) это самый медленный из возможных способов сделать это ... и не только немного; Это на порядок или два медленнее, чем другие варианты.


Обновление В последнее время за это проголосовали, и поэтому я хочу добавить к этому, что с момента публикации я увидел довольно веские доказательства того, что Sql Server оптимизирует разницу в производительности между " правильный и быстрый путь, то есть вы должны отдать предпочтение первому.

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

В большинстве мест база данных уже является вашим узким местом. Как правило, это сервер, который является самым дорогим для добавления оборудования для повышения производительности, и самый сложный для правильной установки этих дополнений (например, вы должны балансировать диски с памятью). Кроме того, его сложнее масштабировать как с технической, так и с деловой точки зрения; Технически гораздо проще добавить веб-сервер или сервер приложений, чем сервер базы данных, и даже если это неверно, вы не платите $ 20 000 за серверную лицензию для IIS или apache.

Смысл, который я пытаюсь подчеркнуть, заключается в том, что по возможности вы должны выполнять эту работу на уровне приложений. только время, когда вы должны урезать дату и время на Sql Server, - это когда вам нужно сгруппировать по дням, и даже в этом случае вам, вероятно, следует установить дополнительный столбец как вычисляемый столбец, сохраняемый при вставке / время обновления или поддерживается в логике приложения. Получите эту тяжелую работу с базами данных из своей базы данных.

44 голосов
/ 29 мая 2009

Только для SQL Server 2008

CAST(@SomeDateTime AS Date) 

Затем приведите его к дате и времени, если хотите

CAST(CAST(@SomeDateTime AS Date) As datetime)
20 голосов
/ 31 мая 2011

Просто для более полного ответа, вот рабочий способ усечения любой из частей даты вниз и включая минуты (замените GETDATE() на дату, которую нужно усечь).

Это отличается от принятого ответа тем, что вы можете использовать не только dd (дни), но и любые части даты (см. здесь ):

dateadd(minute, datediff(minute, 0, GETDATE()), 0)

Обратите внимание, что в приведенном выше выражении 0 является постоянной датой начала года (1900-01-01). Если вам нужно усечь меньшие части, например, секунды или миллисекунды, вам нужно взять постоянную дату, которая ближе к дате, которую нужно усечь, чтобы избежать переполнения.

7 голосов
/ 29 мая 2009

Фрагмент, который я нашел в Интернете, когда мне нужно было сделать это:

 dateadd(dd,0, datediff(dd,0, YOURDATE))
 e.g.
 dateadd(dd,0, datediff(dd,0, getDate()))
1 голос
/ 18 ноября 2009
CONVERT(DATE, <yourdatetime>) or CONVERT(DATE, GetDate()) or CONVERT(DATE, CURRENT_TIMESTAMP)
1 голос
/ 25 июня 2009

В 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 datetime (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

В-третьих, более многословный метод. Для этого необходимо разбить дату на части года, месяца и дня, собрать их в формате «гггг / мм / дд», а затем привести их обратно к дате. Этот метод включает 7 вызовов метода, включая заключительный CAST (), не говоря уже о конкатенации строк.

0 голосов
/ 01 августа 2014

Вы могли бы просто сделать это (SQL 2008):

объявлять @SomeDate date = getdate ()

select @SomeDate

2009-05-28

0 голосов
/ 14 февраля 2014

Oracle:

TRUNC(SYSDATE, 'MONTH')

SQL Server:

DATEADD(DAY, - DATEPART(DAY, DateField) + 1, DateField)

Может использоваться аналогичным образом для усечения минут или часов с даты.

0 голосов
/ 07 ноября 2012

Вы также можете извлечь дату using Substring из переменной даты и времени, а приведение к дате и времени будет игнорировать часть времени.

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)
0 голосов
/ 23 мая 2012

Этот запрос должен дать вам результат, эквивалентный trunc(sysdate) в Oracle.

SELECT  * 
FROM    your_table
WHERE   CONVERT(varchar(12), your_column_name, 101)
      = CONVERT(varchar(12), GETDATE(), 101)

Надеюсь, это поможет!

...