Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Объединение таблиц по нескольким полям  [new]
anyou
Member

Откуда:
Сообщений: 4
Здравствуйте!
В базе данных есть таблица с адресом, состоящим из полей Улица, Дом, Литера, Подъезд, Номер_лифта и поле Регистрационный_номер. Поля Литера и Номер_лифта могут иметь значения NULL.
Пришли новые данные с обновлёнными рег номерами. Из этих данных я создал такую же таблицу.

Нужно объединить таблицы по полному адресу и вывести записи, где новый рег номер отличается от старого.
Следующий запрос не выдаёт ни одного результата. Судя по всему, значения NULL не считаются равными.
select t1.[id_address]
	,('ул. ' + t3.street + ', д.' + CAST(t2.home as nvarchar(10)) + (case when t2.litera is null then '' else t2.litera end) + ' - ' + CAST(t2.porch as nvarchar(10)) + (case when t2.num_lift is null then '' else ' №' + CAST(t2.num_lift as nvarchar(10)) end )) as 'Адрес old'
	,('ул. ' + t6.street + ', д.' + CAST(t5.home as nvarchar(10)) + (case when t5.litera is null then '' else t5.litera end) + ' - ' + CAST(t5.porch as nvarchar(10)) + (case when t5.num_lift is null then '' else ' №' + CAST(t5.num_lift as nvarchar(10)) end )) as 'Адрес new'
      ,t1.[reg_num] as 'reg_num_old'
,t5.[reg_num] as 'reg_num_new'
     
from lifts t1 
join address t2 on t1.id_address = t2.id_address
join streets t3 on t2.id_street = t3.id_street

join db2016 t5 on t3.street = t5.street and t2.home = t5.home and t2.litera = t5.litera and t2.porch = t5.porch and t2.num_lift = t5.num_lift
join streets t6 on t5.id_street = t6.id_street 

--where t1.reg_num != t5.reg_num


Заранее спасибо.
9 дек 16, 08:25    [19982988]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20581
anyou
Судя по всему, значения NULL не считаются равными.
Конечно.
Нужно использовать http://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to
9 дек 16, 09:04    [19983093]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20581
Упс. Пардон, сервером ошибся...
9 дек 16, 09:05    [19983102]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20581
anyou
Поля Литера и Номер_лифта могут иметь значения NULL.

Тогда надо заменять их на нечто, что НЕ МОЖЕТ быть в этом поле, когда НЕ Null. Скажем
WHERE ... COALESCE(t2.num_lift, -1) = COALESCE(t5.num_lift, -1)

Правда, тогда индексы в никуда...

Ну или тупое
WHERE ... (t2.num_lift = t5.num_lift) OR (t2.num_lift IS NULL AND t5.num_lift IS NULL)
9 дек 16, 09:09    [19983114]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
anyou
Member

Откуда:
Сообщений: 4
Akina
anyou
Поля Литера и Номер_лифта могут иметь значения NULL.

Тогда надо заменять их на нечто, что НЕ МОЖЕТ быть в этом поле, когда НЕ Null. Скажем
WHERE ... COALESCE(t2.num_lift, -1) = COALESCE(t5.num_lift, -1)

Правда, тогда индексы в никуда...

Ну или тупое
WHERE ... (t2.num_lift = t5.num_lift) OR (t2.num_lift IS NULL AND t5.num_lift IS NULL)


Спасибо! Я знал, что есть простое решение, без заумных конструкций)

В итоге, вот
select t1.[id_address]
		,('ул. ' + t3.street + ', д.' + CAST(t2.home as nvarchar(10)) + (case when t2.litera is null then '' else t2.litera end) + ' - ' + CAST(t2.porch as nvarchar(10)) + (case when t2.num_lift is null then '' else ' №' + CAST(t2.num_lift as nvarchar(10)) end )) as 'Адрес old'
		,('ул. ' + t6.street + ', д.' + CAST(t5.home as nvarchar(10)) + (case when t5.litera is null then '' else t5.litera end) + ' - ' + CAST(t5.porch as nvarchar(10)) + (case when t5.num_lift is null then '' else ' №' + CAST(t5.num_lift as nvarchar(10)) end )) as 'Адрес new'
      ,t1.[reg_num] as 'reg_num_old'
	  ,t5.[reg_num] as 'reg_num_new'

from lifts t1 
join address t2 on t1.id_address = t2.id_address
join streets t3 on t2.id_street = t3.id_street

join owners t4 on t1.id_owner = t4.id_owner
right outer join db2016 t5 on t3.street = t5.street
join streets t6 on t5.id_street = t6.id_street 

where t2.home = t5.home and t2.porch = t5.porch and coalesce(t2.litera, 'Z') = coalesce(t5.litera, 'Z') and coalesce(t2.num_lift, -1) = coalesce(t5.num_lift, -1)
and t1.reg_num != t5.reg_num

order by t5.street, t5.home, t5.litera, t5.porch, t5.num_lift
9 дек 16, 09:46    [19983277]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
anyou
Member

Откуда:
Сообщений: 4
Правда, насколько я понял, right outer join не влияет на результат и несколько строк он всё же не вывел, но это уже мелочи, разберусь
9 дек 16, 09:49    [19983288]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
Agapov_stas
Member

Откуда:
Сообщений: 402
anyou,
в чем идея?:
автор
join address t2 on t1.id_address = t2.id_address
join streets t3 on t2.id_street = t3.id_street

join owners t4 on t1.id_owner = t4.id_owner
right outer join db2016 t5 on t3.street = t5.street
join streets t6 on t5.id_street = t6.id_street
9 дек 16, 10:26    [19983446]     Ответить | Цитировать Сообщить модератору
 Re: Объединение таблиц по нескольким полям  [new]
iljy
Member

Откуда:
Сообщений: 8711
anyou,

самое правильное - использовать

on exists ( select t3.street, t2.home, t2.litera, t2.porch, t2.num_lift
intersect select t5.street, t5.home, t5.litera, t5.porch, t5.num_lift)


, в этом случае правильно обрабатываются NULL и не теряется возможность использовать индексы.
9 дек 16, 10:32    [19983482]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить