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

Откуда: Саратов
Сообщений: 487
Необходимо соединить 2 таблицы t1 и t2 по условию t1.Id = t2.t1Id(приоритетное условие),
либо по паре других полей(col1, col2), значения в которых составляют уникальную пару либо отсутствуют (рецессивное условие).
Т.е. хотелось бы построить что-то вроде:

select t1.col3, t2.col4
from t1
left join t2 on case when t2.t1ID is not null
			then t1.id = t2.t1ID 
			else t1.col1 = t1.col1 and t1.col2 = t1.col2
		   end	


Но получается пока только:

select t1.col3, coalesce(a.col4,b.col4)  
from t1
left join t2 a on a.t1Id = t1.ID
left join t2 b on b.col1 = t1.col1 and b.col2 = t2.col2


Есть ли вариант решения этой задачи без двойного join'a таблицы t2 ?

Сейчас выполняю запрос на SQL Server 2008 R2, но в принципе интересны варианты и для более поздних версий.
27 сен 16, 13:58    [19713400]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4902
[quot Шамиль Фаридович]
select t1.col3, t2.col4
from t1
left join t2 on case when t2.t1ID is not null
			then t1.id = t2.t1ID 
			else t1.col1 = t1.col1 and t1.col2 = t1.col2
		   end	


А чем вас не устраивает написанный вами же запрос?
27 сен 16, 14:11    [19713521]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3422
Шамиль Фаридович,

А в t1 все поля обязательные, или тоже NULL'ы могут быть?
27 сен 16, 14:14    [19713540]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
Шамиль Фаридович
Т.е. хотелось бы построить что-то вроде:

select t1.col3, t2.col4
from t1
left join t2 on case when t2.t1ID is not null
			then t1.id = t2.t1ID 
			else t1.col1 = t1.col1 and t1.col2 = t1.col2
		   end	



ну дак в чем проблема

select t1.col3, t2.col4
from t1
left join t2 on ((t2.t1ID is not null and t1.id = t2.t1ID) or ( t2.t1ID is null and t1.col1 = t1.col1 and t1.col2 = t1.col2))	
27 сен 16, 14:27    [19713620]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6802
WarAnt
Шамиль Фаридович
Т.е. хотелось бы построить что-то вроде:

select t1.col3, t2.col4
from t1
left join t2 on case when t2.t1ID is not null
			then t1.id = t2.t1ID 
			else t1.col1 = t1.col1 and t1.col2 = t1.col2
		   end	



ну дак в чем проблема

select t1.col3, t2.col4
from t1
left join t2 on ((t2.t1ID is not null and t1.id = t2.t1ID) or ( t2.t1ID is null and t1.col1 = t1.col1 and t1.col2 = t1.col2))	

оптимизатор может обидеться :)
27 сен 16, 14:29    [19713637]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
uaggster
Member

Откуда:
Сообщений: 1068
[quot a_voronin]
Шамиль Фаридович
select t1.col3, t2.col4
from t1
left join t2 on case when t2.t1ID is not null
			then t1.id = t2.t1ID 
			else t1.col1 = t1.col1 and t1.col2 = t1.col2
		   end	


А чем вас не устраивает написанный вами же запрос?

Вот именно.
Case - именно так и работает. Срабатывает первое по порядку сверху вниз верное условие.
Если условия and/or - выполняются так, как это удобно оптимизатору, в любой последовательности, то CASE - именно так, как описано в условии.
В чем проблема то?
27 сен 16, 15:14    [19713904]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
Шамиль Фаридович
Member

Откуда: Саратов
Сообщений: 487
a_voronin, uaggster
тем, что он синтаксически не верен (по крайней мере в SQL 2008 R2)

Ennor Tiegael
Шамиль Фаридович,
А в t1 все поля обязательные, или тоже NULL'ы могут быть?


(col1, col2) nullable в обеих таблицах. Но интересно, что от этого изменится?

WarAnt, TaPaK
Да, в основном конечно в оптимизаторе (по t1ID индекс есть, по паре других столбцов нет) + есть маленький шанс, что t1.ID и пара (col1,col2) будут соответствовать разные записям в t2 (в этом случае вариант WarAnt'a вернет 2 строки вместо одной)

Если немного скорректировать мой запрос
+

select t1.col3, coalesce(a.col4,b.col4)
from t1
left join t2 a on a.t1Id = t1.ID
left join t2 b on b.t1Id is null and b.col1 = t1.col1 and b.col2 = t2.col2

то второй join начинает также использовать индекс по t1Id, и работает немного быстрее.

Ладно, как оптимизировать я разберусь сам, суть вопроса была в наличии конструкции для построения соединения по "приоритетного условию" без повторного join'a.
Раз она до сих пор никому не пришла в голову, значит ее наверное нет.
27 сен 16, 16:04    [19714293]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 6802
Шамиль Фаридович,

UNION ALL воообщем можно получить более оптимизированный вариант
27 сен 16, 16:10    [19714332]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
Шамиль Фаридович
(col1, col2) nullable в обеих таблицах. Но интересно, что от этого изменится?
Ничего себе!

Но в таком случае, например, t1.col1 = t1.col1 эквивалентно t1.col1 IS NOT NULL.
Ибо троичную логику никто не отменял.

Ошибка ваша в том, что CASE - функция, возвращающая одно скалярное значение какого-нибудь определённого типа.
Результат сравнениея имеет булевый тип, а такого явного типа в TSQL нет.
Значит, для разных результатов сравнения надо возвращать разный результат, например, целого или строкового типа.
А анализировать его где-то снаружи CASE
27 сен 16, 16:33    [19714479]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
WarAnt
Member

Откуда: Питер
Сообщений: 2423
TaPaK
WarAnt
пропущено...


ну дак в чем проблема

select t1.col3, t2.col4
from t1
left join t2 on ((t2.t1ID is not null and t1.id = t2.t1ID) or ( t2.t1ID is null and t1.col1 = t1.col1 and t1.col2 = t1.col2))	

оптимизатор может обидеться :)


Дак про оптимизатор никто не спрашивал.
Если нужно и быстро тогда union + not exists
27 сен 16, 16:56    [19714619]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
Шамиль Фаридович
Member

Откуда: Саратов
Сообщений: 487
iap
А анализировать его где-то снаружи CASE

В точку. Видимо подсознательно отбросил это вариант, посчитав, что оптимизатору будет сложно в этом случае использовать индекс:
+
select t1.col3, t2.col4
from t1
left join t2 
		on case when t2.t1ID is not null
			then when t1.id = t2.t1ID then 1 else 0 end
			else when t1.col1 = t1.col1 and t1.col2 = t1.col2 then 1 else 0 end
		   end	= 1		


TaPaK,
Хорошая идея с UNION ALL
+
select t1.col3, t2.col4
from t1
left join t2 on t2.t1Id = t1.ID
union all
select t1.col3, t2.col4
left join t2 b on b.col1 = t1.col1 and b.col2 = t2.col2
where t2.t1Id is null

Но пока останавливаюсь на своем варианте, он в контексте моей реальной задачи немного быстрее (в других контекстах возможно будет ваш)

WarAnt
union + not exists

Не понял, что конкретно вы имели в иду.
27 сен 16, 18:28    [19715083]     Ответить | Цитировать Сообщить модератору
 Re: Приоритетное условие соединения таблиц  [new]
FOX75
Member

Откуда:
Сообщений: 29
Как по мне все груговерти со скриптом... ниочем. Реальный план и IO-сы наше все ... ИМХО
29 сен 16, 09:43    [19721937]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить