13 ответов:
Это продолжает часто собирать дополнительные голоса, даже несколько лет спустя, и поэтому мне нужно обновить его для современных версий 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. Он будет работать независимо от того, как хранится ваш datetime и независимо от того, что ваш язык.
быстрый способ:
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 или апаш.
смысл, который я пытаюсь сделать, заключается в том, что по возможности вы должны выполнять эту работу на уровне приложения. Элемент только время, когда вы должны когда-либо найти себе усечение datetime на Sql Server, когда вам нужно группировать по дням, и даже тогда вы, вероятно, должны иметь дополнительный столбец, настроенный как вычисляемый столбец, поддерживаемый во время вставки/обновления или поддерживаемый в логике приложения. Получить этот индекс ломать, cpu-тяжелая работа от вашей базы данных.
только для 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 вызова метода, включая final 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 вызовов методов, включая final CAST (), не говоря уже о конкатенации строк.
выберите cast (floor (cast (getdate () as float)) как datetime) Ссылка на это: http://microsoftmiles.blogspot.com/2006/11/remove-time-from-datetime-in-sql-server.html
для тех из вас, кто пришел сюда в поисках способа усечь поле 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)(всегда ставлю
.0в конце неявно привести к a плыть.)
для тех из вас интересно, что
(3.0/86400000)для моего расчета SQL Server 2005, похоже, не отбрасывается изFLOATдоDATETIMEточно, так что это добавляет 3 миллисекунды, прежде чем настилать его.
этот запрос должен дать вам результат, эквивалентный
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)можно аналогичным образом использовать для усечения минут или часов от даты.
вы могли бы просто сделать это (SQL 2008):
declare @SomeDate date = getdate ()
select @SomeDate
2009-05-28
TRUNC (aDate, 'DD') будет усекать мин, сек и ч
SRC:http://www.techonthenet.com/oracle/functions/trunc_date.php
Comments