Самый эффективный способ в SQL Server получить дату с даты + времени?

В MS SQL 2000 и 2005, учитывая дату и время, например «2008-09-25 12:34:56», каков наиболее эффективный способ получить дату и время, содержащую только «2008-09-25»?

Дублированный здесь.

Мне очень приятно, что первые три ответа все разные, значит, это не глупый вопрос! :)

Matt Howells 25.09.2008 16:48
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
74
2
76 714
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

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 г.).

Вы уверены, что это самый эффективный метод?

Matt Howells 25.09.2008 17:02

Мои тесты показывают, что метод Мэтта немного быстрее. Я также считаю его более читаемым.

Darrel Miller 25.09.2008 17:32

@Dar На мой взгляд, преобразование в float - плохая практика, потому что преобразование туда и обратно в datetime ненадежно. См. этот пост для более подробной информации.

ErikE 13.09.2010 04:08

select cast(floor(cast(@datetime as float)) as datetime)

Работает, потому что приведение datetime к float дает количество дней (включая доли дня) с 1 января 1900 года. Floating убирает дробные дни и оставляет количество полных дней, которое затем можно вернуть к datetime.

Я использую тот же метод, и он отлично работает. Насколько я помню, DATETIME физически хранится как FLOAT, так что этот метод очень эффективен. Также я помню, как где-то читал, что он использовался внутри Microsoft. Не уверен, что это все еще так с SS2008

kristof 25.09.2008 17:48

SQL2008 имеет значительно улучшенные (и столь необходимые) функции обработки даты. Это было бы так же просто, как приведение datetime к новому типу даты.

Matt Howells 25.09.2008 19:37

@kristof datetime физически не хранится как float. Это два 4-байтовых целых числа, первое из которых - количество дней с 1900-1-1, а второе - количество тиков 1/300 секунды с полуночи. И последнее, на мой взгляд, преобразование в float - плохая практика, потому что преобразование туда и обратно в datetime ненадежно. См. этот пост для более подробной информации.

ErikE 13.09.2010 04:07

Похоже, он хранится как фиксированная точка, а не как плавающая точка внутри.

Reversed Engineer 06.02.2018 11:22

Чтобы получить ГГГГ-ММ-ДД, используйте:

select convert(varchar(10), getdate(), 120)

Редактировать: К сожалению, он хочет DateTime вместо строки. Эквивалент TRUNC () в Oracle. Вы можете взять то, что я опубликовал, и вернуть DateTime:

select convert(datetime, convert(varchar(10), getdate(), 120) , 120)

Обратите внимание, что преобразование в varchar происходит медленнее. См. этот пост для более подробной информации.

ErikE 13.09.2010 04:09

CONVERT(VARCHAR(10), GETDATE(), 120) AS [YYYY-MM-DD]

Обратите внимание, что преобразование в varchar происходит медленнее. См. этот пост для более подробной информации.

ErikE 13.09.2010 04:09

CONVERT, FLOOR и DATEDIFF будут работать одинаково.

Как вернуть часть даты только из типа данных SQL Server datetime

Это неправда. См. Связанный поток для обновления или просто перейдите к этот пост для более подробной информации.

ErikE 13.09.2010 04:09

Три метода описаны по ссылке ниже. Я не проверял их производительность, чтобы определить, какой из них самый быстрый.

http://www.blackwasp.co.uk/SQLDateFromDateTime.aspx

Ответ принят как подходящий

Должен признаться, что раньше Мэтт не видел конверсии напольного поплавка. Я должен был это проверить.

Я протестировал чистый выбор (который вернет дату и время, а не то, что мы хотим), преобладающее решение здесь (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 ненадежно. Во-вторых, см. этот пост с большим количеством тестов производительности различных методов.

ErikE 13.09.2010 04:06

select cast(getdate()as varchar(11))as datetime

Обратите внимание, что преобразование в varchar происходит медленнее. См. этот пост для более подробной информации.

ErikE 13.09.2010 04:10

CAST(FLOOR(CAST(yourdate AS DECIMAL(12, 5))) AS DATETIME) на сегодняшний день работает лучше всех. вы можете увидеть доказательства и тесты, когда получение даты без времени на сервере sql

Почему бы не протестировать также dateadd / dateiff?

gbn 13.12.2010 09:35

Что насчет SELECT CAST(CASt(GETDATE() AS int) AS DATETIME) ??

Потому что OP не об этом просил ..?

mbinette 05.11.2012 05:38

Я попробовал; он может округлить ВВЕРХ, что даст неверный результат.

Pete Alvin 14.06.2017 21:44

в SQL Server 2012 используйте

select cast(getdate() as date)

Хотя это правда, вопрос касается более старых версий MS SQL 2000 и 2005, в которых отсутствует тип данных date.

jpw 25.03.2015 20:24

Другие вопросы по теме