SQL Самый быстрый способ сравнить две даты (нестандартный формат varchar и datetime) - PullRequest
4 голосов
/ 23 сентября 2010

У меня есть два поля даты, к которым мне нужно присоединиться.

Первый - это обычное время в формате yyyy-mm-dd hh:mm:ss

Второй - это varchar (8) в дочернем формате рыжего шага mmddyyyy

Теперь это становится болезненным, потому что нет простого способа преобразования в соответствующий тип. Существует встроенный формат yyyymmdd, но он не соответствует формату varchar.

Я вижу два пути:

declare @normal_date as datetime;
declare @hated_date as varchar(8);

set @normal_date='1974-11-01 00:00:00.000'
set @hated_date='11011974'

--cast to date time with string splits
select @normal_date
where CONVERT(datetime, RIGHT(@hated_date,4)+LEFT(@hated_date,2)+SUBSTRING(@hated_date,3,2))=@normal_date

--convert normal date to ackward format
select @normal_date
      where REPLACE(CONVERT(varchar(10),@normal_date,101), '/','')=@hated_date

Что лучше? Или есть лучший способ?

Отредактировано, чтобы показать расходы

--Operator cost (39%)
CONVERT(datetime, RIGHT(@hated_date,4)+LEFT(@hated_date,2)+SUBSTRING(@hated_date,3,2))=@normal_date

--Operator cost (57%)
REPLACE(CONVERT(varchar(10),@normal_date,101), '/','')=@hated_date

--Operator cost (46%)
cast(stuff(stuff(@hated_date, 3,0, '/'),6,0,'/') as datetime)=@normal_date

--Operator cost (47%)
RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)=@normal_date

Ответы [ 4 ]

5 голосов
/ 23 сентября 2010

Это ггггммдд нет?

RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)

Итак, ваш сценарий становится

declare @normal_date as datetime;
declare @hated_date as varchar(8);

set @normal_date='1974-11-01 00:00:00.000'
set @hated_date='11011974'

--SELECT @hated_date = RIGHT(@hated_date, 4) + LEFT(@hated_date, 4))

select 'hurrah' WHERE @normal_date = RIGHT(@hated_date, 4) + LEFT(@hated_date, 4)
2 голосов
/ 24 сентября 2010

Предложите либо исправить столбец на datetime, либо добавить столбец datetime в таблицу и преобразовать данные, чтобы вам приходилось выполнять это преобразование только один раз при вводе данных (и, разумеется, для существующих данных) Пробалы даже быть просчитанным столбцом. Это НЕ то, что вы хотите делать в операторах выбора. При необходимости создайте таблицу преобразования даты с каждой возможной датой в обоих форматах и ​​присоединитесь к ней, если таблица не может быть изменена.

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

2 голосов
/ 23 сентября 2010

Другой подход заключается в следующем:

MONTH(@normal_date)*1000000 + DAY(@normal_date)*10000 + YEAR(@normal_date)
=
CAST(@hated_date AS INT)

еще одна вещь: точнее сравнивать реальные затраты на исполнение, чем полагаться на оценки оптимизатора.

2 голосов
/ 23 сентября 2010

Попробуйте это:

select cast(stuff(stuff('11011974', 3,0, '/'),6,0,'/') as datetime)

Обновление

alt text

...