我最近发现LEFT JOIN的ON子句可能包含诸如(1 = 1)之类的值。
这令我感到不安,因为它打破了我对连接功能的看法。
我遇到了以下情况的更精细版本:
SELECT DISTINCT Person.ID, ...
FROM Person LEFT JOIN Manager
ON (Manager.ID = Person.ID OR Manager.ID = -1))
WHERE (...)
这完全合法。如果有的话,“Manager.ID = -1”会完成什么?这怎么会影响Join?
答案 0 :(得分:7)
如果人员表是:
id name
1 Person One
2 Person Two
3 Person Three
4 Person Four
5 Person Five
如果经理表是
id name
-1 Admin
2 Manager One
3 Manager Two
如果查询是:
SELECT DISTINCT *
FROM Person LEFT JOIN Manager
ON (Manager.id = Person.id OR Manager.id = -1)
然后结果是:
Person One -1 Admin
Person Two -1 Admin
Person Two 2 Manager One
Person Three -1 Admin
Person Three 3 Manager Two
Person Four -1 Admin
Person Five -1 Admin
此处所有人行与-1 Admin(在经理表上)连接,如果经理表中存在相同的ID,则会再发生一次连接。
答案 1 :(得分:5)
除非在Manager表中有一行id等于-1,否则它什么都不做。如果有这样的行,那么该行将始终连接到person表中的每一行。因此,对于每个Person行,您可能在查询输出中获得两个ros,一个使用manager.id =到person的id,另一个使用Manager.ID = -1 row
答案 2 :(得分:5)
您还将看到用于进一步过滤记录的AND子句。这在处理外连接时非常重要,因为将这些过滤操作添加到caluse会将连接从左连接转换为内连接(除非它类似于t.idfield为null)。
下面我将展示这是如何工作的以及为什么将过滤碰撞放在正确的位置很重要。
create table #test(test1id int,test varchar(10)) create table#test2(test2id int,test1id int,test2 varchar(10))
insert into #test (test1id, test)
select 1, 'Judy'
union all
select 2, 'Sam'
union all
select 3, 'Nathan'
insert into #test2 (test2id, test1id, test2)
select 1,1,'hello'
union all
select 2,1,'goodbye'
union all
select 3,2,'hello'
select * from #test t
left join #test2 t2 on t.test1id = t2.test1id
where test2 = 'goodbye'
--result set
--test1id test test2id test1id test2
--1 Judy 2 1 goodbye
select * from #test t
left join #test2 t2 on t.test1id = t2.test1id
and test2 = 'goodbye'
--result set
--test1id test test2id test1id test2
--1 Judy 2 1 goodbye
--2 Sam NULL NULL NULL
--3 Nathan NULL NULL NULL
您可以使用某些字段为空的位置(假设您选择一个永远不会为空的字段)来获取第一个表中的记录而不是第二个表中的记录:
select * from #test t
left join #test2 t2 on t.test1id = t2.test1id
where test2id is null
--result set
--test1id test test2id test1id test2
--3 Nathan NULL NULL NULL