Самый эффективный способ в SQL Server, чтобы получить дату от даты + время? - PullRequest
73 голосов
/ 25 сентября 2008

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

Дублируется здесь .

Ответы [ 11 ]

111 голосов
/ 30 сентября 2008

Должен признать, что раньше я не видел конвертацию в пол-поплавок, показанную Мэттом. Я должен был проверить это.

Я проверил чистый выбор (который будет возвращать дату и время, а не то, что нам нужно), правящее решение здесь (floor-float), общее «наивное», упомянутое здесь (stringconvert) и упомянутое здесь что я использовал (как я думал, это было самым быстрым).

Я протестировал запросы на тестовом сервере MS SQL Server 2005, работающем на сервере Win 2003 SP2 с процессором 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: время ЦП = 0 мс, прошедшее время = 1 мс.

(затронуто 1000000 строк) Таблица 'tblMeasureLogv2'. Сканирование 1, логическое чтение 4752, физическое чтение 0, чтение с опережением 0, чтение логического объекта 0, чтение с физического объекта 0, чтение с опережением 0.

Время выполнения SQL Server: время ЦП = 422 мс, прошедшее время = 33803 мс.

(затронуто 1000000 строк) Таблица 'tblMeasureLogv2'. Сканирование 1, логическое чтение 4752, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.

Время выполнения SQL Server: время ЦП = 625 мс, прошедшее время = 33545 мс.

(затронуто 1000000 строк) Таблица 'tblMeasureLogv2'. Сканирование 1, логическое чтение 4752, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.

Время выполнения SQL Server: время ЦП = 1953 мс, прошедшее время = 33843 мс.

(затронуто 1000000 строк) Таблица 'tblMeasureLogv2'. Сканирование 1, логическое чтение 4752, физическое чтение 0, чтение с опережением 0, логическое чтение с 0, физическое чтение с 0, чтение с опережением 0.

Время выполнения SQL Server: время ЦП = 531 мс, прошедшее время = 33440 мс. Время анализа и компиляции SQL Server: время ЦП = 0 мс, прошедшее время = 1 мс.

Время выполнения SQL Server: время ЦП = 0 мс, прошедшее время = 1 мс.

Что мы здесь видим?

Давайте сосредоточимся на времени процессора (мы смотрим на преобразование), и мы увидим, что у нас есть следующие числа:

Pure-Select:  422
Floor-cast:   625
String-conv: 1953
DateAdd:      531  

Из этого мне кажется, что DateAdd (по крайней мере, в данном конкретном случае) немного быстрее, чем метод приведения к полу.

Перед тем, как перейти туда, я несколько раз запускал этот тест, с измененным порядком запросов, с одинаковыми результатами.

Это что-то странное на моем сервере или как?

23 голосов
/ 25 сентября 2008
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 г.).

12 голосов
/ 25 сентября 2008
select cast(floor(cast(@datetime as float)) as datetime)

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

7 голосов
/ 25 марта 2015

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

select cast(getdate() as date)
1 голос
/ 21 ноября 2008
select cast(getdate()as varchar(11))as datetime
0 голосов
/ 07 декабря 2011

А как же SELECT CAST(CASt(GETDATE() AS int) AS DATETIME) ??

0 голосов
/ 13 декабря 2010

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

0 голосов
/ 26 сентября 2008

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

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

0 голосов
/ 25 сентября 2008

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

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

0 голосов
/ 25 сентября 2008
CONVERT(VARCHAR(10), GETDATE(), 120) AS [YYYY-MM-DD]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...