内连接的反面是什么?对于表格Person (int PersonId, varchar PersoName, int AddrId)
,我想知道Person中的行AddrId
,Address
表中没有行。
答案 0 :(得分:55)
内连接的反面是什么?
OUTER联接,可以有三个选项:
This is a good visual representation of JOINs
我想知道Person中有没有AddrId的行,这些行在Address表中没有行。
SELECT p.*
FROM PERSON p
LEFT JOIN ADDRESS a ON a.addrid = p.addrid
WHERE a.addrid IS NULL
SELECT p.*
FROM PERSON p
WHERE NOT EXISTS(SELECT NULL
FROM ADDRESS a
WHERE a.addrid = p.addrid)
SELECT p.*
FROM PERSON p
WHERE p.addrid NOT IN (SELECT a.addrid
FROM ADDRESS a)
答案 1 :(得分:7)
内部联接不是外部联接的直径。它们用于不同的目的。但是,从一个表中查找不存在于另一个表中的行的常见模式是使用外部联接:
Select ...
From Table1
Left Join Table2
On Table2.ForeignKeyCol = Table1.PrimaryKeyCol
Where Table2.PrimaryKeyCol Is Null
这将返回Table1中的所有行以及Table2中的任何匹配行,这样,如果给定的Table1行没有Table2匹配,则返回Table2列的null。然后要求非可空列(Table2.PrimaryKeyCol)为空,我将从Table1获取Table2中不存在的所有行。使用示例表名称,我们会有类似的内容:
Select ...
From Person
Left Join Address
On Address.PersonId = Person.Id
Where Address.Id Is Null
答案 2 :(得分:4)
如果您将内部联接视为满足特定条件的两个表的行,则相反的是 表中的行不会。
例如,以下内容将选择地址表中包含地址的所有人:
SELECT p.PersonName, a.Address
FROM people p
JOIN addresses a
ON p.addressId = a.addressId
我想这与“相反”是选择没有地址的所有人和没有人的所有地址。然而,这似乎不是你要问的,你似乎只对这个问题的一个组成部分感兴趣:地址表中没有地址的所有人。
为此,左连接最好:
SELECT p.PersonName
FROM people p
LEFT JOIN addresses a
ON p.addressId = a.addressId
WHERE a.addressId IS NULL
请注意,通常有些人喜欢以不同的方式编写它,因为他们认为它更具可读性(但根据我对大型表的体验,它的表现比上述方式更差):
SELECT PersonName
FROM people
WHERE addressId NOT IN (SELECT addressId FROM addresses)
答案 3 :(得分:0)
我认为最好的解决方案是使用EXISTS
。像这样:
SELECT * FROM Person P
WHERE P.AddrId IS NOT NULL
AND NOT EXISTS ( SELECT 1 FROM Address A WHERE A.AddrId = P.AddrId )
上面的查询将返回每个设置了AddrId但在地址表中没有相应记录的人。
Obs。:使用EXISTS
查询中的常量1来避免表格访问。