#sql-server-2008
#sql-server-2008
Вопрос:
В SQL Server 2008 R2 мне нужно сравнить две даты рождения из разных таблиц.
- столбец
C.date_of_birth
имеет типDATETIME
- столбец
R.dob
— это дата, сохраненная какVARCHAR
, но без начальных нулей в частях месяца или дня, чтобы сделать ее длину согласованной (<- это сложная часть).
Я приблизился к этому:
where R.dob <> convert(varchar, cast(C.date_of_birth as DATE), 101)
но это возвращает слишком много строк, потому что 1/5/1923
in R.dob
не соответствует 01/05/1923
in C.date_of_birth
.
Как я могу отформатировать, R.dob
чтобы его можно было правильно сравнить с C.date_of_birth
?
Спасибо.
Комментарии:
1. почему datetime хранится как varchar? Если вы можете, устраните причину, а не симптомы.
2. … в противном случае преобразуйте переменную в date (не наоборот), а затем сравните две даты.
3. И каков правильный синтаксис преобразования varchar в date? Я перепробовал все, что мог придумать, и большинство выдает ошибку «Ошибка преобразования при преобразовании даты и / или времени из символьной строки». Я пробовал CAST (R.dob как DATETIME2), CONVERT (datetime, R.dob, 101) и любую другую комбинацию, о которой я могу думать. Извините — долгий день.
4. @user477526: правильный синтаксис был бы
CAST(r.dob AS DATE)
, если вас интересует только часть даты (не время). ОДНАКО: большая проблема, которую я вижу, заключается в том, что вашеR.dob
представление даты зависит от языковых / региональных настроек — и это просто ад. Я согласен с Митчем: вы должны исправить корневую проблему и сделать этоDATE
столбцом — иначе вы будете бороться и дергать себя за волосы до конца своих дней….
Ответ №1:
Вы можете использовать свой varchar в качестве datetime. Например, результат этого:
select cast('1/5/1923' as datetime)
Было бы 1923-01-05 00:00:00.000
Затем вы можете просто использовать DATEDIFF()
для сравнения их, чтобы увидеть, какие из них равны дню (или любому желаемому интервалу).
Ответ №2:
Как насчет этого?
declare @date_of_birth datetime = '1923-01-05',
@dob varchar(10) = '01/05/1923'
select @date_of_birth,
CONVERT(datetime, @dob, 101), -- 101: mm/dd/yyyy
case when @date_of_birth = CONVERT(datetime, @dob, 111)
then 1 else 0
end result
Комментарии:
1. Спасибо, Рубенс. Я попытался ПРЕОБРАЗОВАТЬ (datetime, R.dob, 101), но выдает ошибку «Ошибка преобразования при преобразовании даты и / или времени из символьной строки». Кстати, R.dob хранится как VARCHAR(4096).
Ответ №3:
Я бы попытался привести поле varchar к дате и выполнить сравнение; например, все эти форматы можно легко преобразовать в тип даты:
SELECT cast ( '1/1/2011' as date) col1
union
SELECT cast ( '01/11/2011' as date) col1
union
SELECT cast ( 'Oct 7 2011' as date) col1
union
SELECT cast ( '2011-02-23' as date) col1
Выводит:
col1
----------
2011-01-01
2011-01-11
2011-02-23
2011-10-07
Итак, в вашем запросе вы можете сравнивать даты с датами.
Ответ №4:
Как говорили другие, первым вариантом было бы изменить тип данных R.Dob
на Date
.
В противном случае вы должны привести свое значение varchar
к date
, и в своих комментариях вы получите ошибку при этом. Причина этого, вероятно, в том, что у вас недопустимые даты в столбце. Вы могли бы использовать функцию isdate, чтобы выяснить, какие строки имеют недопустимые даты.
Другой причиной может быть то, что ваш SQL Server не знает, как интерпретировать ваши строки даты. Я не знаю, как интерпретировать это значение 1/5/1923
так откуда SQL Server мог знать?
Используйте set dateformat, чтобы указать SQL Server, как интерпретировать строку даты.
set dateformat mdy
select cast('1/5/1923' as date)
set dateformat dmy
select cast('1/5/1923' as date)
Результат:
----------
1923-01-05
----------
1923-05-01