В MS SQL 2000 и 2005, учитывая дату и время, например «2008-09-25 12:34:56», каков наиболее эффективный способ получить дату и время, содержащую только «2008-09-25»?
Дублированный здесь.
возможный дубликат Какой НАИЛУЧШИЙ способ удалить временную часть значения datetime (SQL Server)?


Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0)
DateDiff (Day, 0, GetDate ()) совпадает с DateDiff (Day, '1900-01-01', GetDate ())
Поскольку DateDiff возвращает целое число, вы получите количество дней, прошедших с 1 января 1900 года. Затем вы прибавляете это целое число дней к 1 января 1900 года. В результате компонент времени удаляется.
Я также должен упомянуть, что этот метод работает для любой части даты / времени (например, года, квартала, месяца, дня, часа, минуты и секунды).
Select DateAdd(Year, DateDiff(Year, 0, GetDate()), 0)
Select DateAdd(Quarter, DateDiff(Quarter, 0, GetDate()), 0)
Select DateAdd(Month, DateDiff(Month, 0, GetDate()), 0)
Select DateAdd(Day, DateDiff(Day, 0, GetDate()), 0)
Select DateAdd(Hour, DateDiff(Hour, 0, GetDate()), 0)
Select DateAdd(Second, DateDiff(Second, '20000101', GetDate()), '20000101')
Последний, секундный, требует особого обращения. Если вы используете 1 января 1900 г., вы получите сообщение об ошибке.
Разница в двух столбцах даты и времени вызвала переполнение во время выполнения.
Вы можете обойти эту ошибку, используя другую контрольную дату (например, 1 января 2000 г.).
Вы уверены, что это самый эффективный метод?
Мои тесты показывают, что метод Мэтта немного быстрее. Я также считаю его более читаемым.
@Dar На мой взгляд, преобразование в float - плохая практика, потому что преобразование туда и обратно в datetime ненадежно. См. этот пост для более подробной информации.
select cast(floor(cast(@datetime as float)) as datetime)
Работает, потому что приведение datetime к float дает количество дней (включая доли дня) с 1 января 1900 года. Floating убирает дробные дни и оставляет количество полных дней, которое затем можно вернуть к datetime.
Я использую тот же метод, и он отлично работает. Насколько я помню, DATETIME физически хранится как FLOAT, так что этот метод очень эффективен. Также я помню, как где-то читал, что он использовался внутри Microsoft. Не уверен, что это все еще так с SS2008
SQL2008 имеет значительно улучшенные (и столь необходимые) функции обработки даты. Это было бы так же просто, как приведение datetime к новому типу даты.
@kristof datetime физически не хранится как float. Это два 4-байтовых целых числа, первое из которых - количество дней с 1900-1-1, а второе - количество тиков 1/300 секунды с полуночи. И последнее, на мой взгляд, преобразование в float - плохая практика, потому что преобразование туда и обратно в datetime ненадежно. См. этот пост для более подробной информации.
Похоже, он хранится как фиксированная точка, а не как плавающая точка внутри.
Чтобы получить ГГГГ-ММ-ДД, используйте:
select convert(varchar(10), getdate(), 120)
Редактировать: К сожалению, он хочет DateTime вместо строки. Эквивалент TRUNC () в Oracle. Вы можете взять то, что я опубликовал, и вернуть DateTime:
select convert(datetime, convert(varchar(10), getdate(), 120) , 120)
Обратите внимание, что преобразование в varchar происходит медленнее. См. этот пост для более подробной информации.
CONVERT(VARCHAR(10), GETDATE(), 120) AS [YYYY-MM-DD]
Обратите внимание, что преобразование в varchar происходит медленнее. См. этот пост для более подробной информации.
CONVERT, FLOOR и DATEDIFF будут работать одинаково.
Как вернуть часть даты только из типа данных SQL Server datetime
Это неправда. См. Связанный поток для обновления или просто перейдите к этот пост для более подробной информации.
Три метода описаны по ссылке ниже. Я не проверял их производительность, чтобы определить, какой из них самый быстрый.
Должен признаться, что раньше Мэтт не видел конверсии напольного поплавка. Я должен был это проверить.
Я протестировал чистый выбор (который вернет дату и время, а не то, что мы хотим), преобладающее решение здесь (floor-float), обычное `` наивное '' решение, упомянутое здесь (stringconvert), и упомянутое здесь, что я был с помощью (как я думал, он был самым быстрым).
Я тестировал запросы на тестовом сервере MS SQL Server 2005, работающем на Win 2003 SP2 Server с процессором Xeon 3GHz, работающим с максимальной памятью (32 бит, то есть около 3,5 Гб). Я нахожусь в ночи, поэтому машина почти без нагрузки работает на холостом ходу. Все это у меня есть.
Вот журнал моего тестового запуска, выбранного из большой таблицы, содержащей временные метки, изменяющиеся до уровня миллисекунды. Этот конкретный набор данных включает даты в диапазоне более 2,5 лет. В самой таблице более 130 миллионов строк, поэтому я ограничиваюсь верхним миллионом.
SELECT TOP 1000000 CRETS FROM tblMeasureLogv2
SELECT TOP 1000000 CAST(FLOOR(CAST(CRETS AS FLOAT)) AS DATETIME) FROM tblMeasureLogv2
SELECT TOP 1000000 CONVERT(DATETIME, CONVERT(VARCHAR(10), CRETS, 120) , 120) FROM tblMeasureLogv2
SELECT TOP 1000000 DATEADD(DAY, DATEDIFF(DAY, 0, CRETS), 0) FROM tblMeasureLogv2
SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 1 ms.
(1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 422 ms, elapsed time = 33803 ms.
(1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 625 ms, elapsed time = 33545 ms.
(1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 1953 ms, elapsed time = 33843 ms.
(1000000 row(s) affected) Table 'tblMeasureLogv2'. Scan count 1, logical reads 4752, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times: CPU time = 531 ms, elapsed time = 33440 ms. SQL Server parse and compile time: CPU time = 0 ms, elapsed time = 1 ms.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms.
Что мы здесь видим?
Давайте сосредоточимся на процессоре (мы смотрим на преобразование), и мы видим, что у нас есть следующие числа:
Pure-Select: 422
Floor-cast: 625
String-conv: 1953
DateAdd: 531
Из этого мне кажется, что DateAdd (по крайней мере, в этом конкретном случае) немного быстрее, чем метод заливки пола.
Прежде чем вы туда отправитесь, я несколько раз запускал этот тест, меняя порядок запросов, и результаты совпадали.
На моем сервере что-то странное, что ли?
Это совсем не странно. Во-первых, на мой взгляд, преобразование в float - плохая практика, потому что преобразование туда и обратно в datetime ненадежно. Во-вторых, см. этот пост с большим количеством тестов производительности различных методов.
select cast(getdate()as varchar(11))as datetime
Обратите внимание, что преобразование в varchar происходит медленнее. См. этот пост для более подробной информации.
CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME) на сегодняшний день работает лучше всех. вы можете увидеть доказательства и тесты, когда получение даты без времени на сервере sql
Почему бы не протестировать также dateadd / dateiff?
Что насчет SELECT CAST(CASt(GETDATE() AS int) AS DATETIME) ??
Потому что OP не об этом просил ..?
Я попробовал; он может округлить ВВЕРХ, что даст неверный результат.
в SQL Server 2012 используйте
select cast(getdate() as date)
Хотя это правда, вопрос касается более старых версий MS SQL 2000 и 2005, в которых отсутствует тип данных date.
Мне очень приятно, что первые три ответа все разные, значит, это не глупый вопрос! :)