【发布时间】:2011-03-26 03:50:16
【问题描述】:
内连接的反面是什么?对于表 Person (int PersonId, varchar PersoName, int AddrId),我想知道在 Person with bad AddrId 中没有在 Address 表中的行。
【问题讨论】:
内连接的反面是什么?对于表 Person (int PersonId, varchar PersoName, int AddrId),我想知道在 Person with bad AddrId 中没有在 Address 表中的行。
【问题讨论】:
内连接与外连接不同。它们服务于不同的目的。但是,从一个表中查找另一个表中不存在的行的常见模式是使用外连接:
Select ...
From Table1
Left Join Table2
On Table2.ForeignKeyCol = Table1.PrimaryKeyCol
Where Table2.PrimaryKeyCol Is Null
这将返回 Table1 中的所有行和 Table2 中的任何匹配行,这样如果给定的 Table1 行没有 Table2 匹配,则返回 Table2 列的空值。然后要求不可为空的列 (Table2.PrimaryKeyCol) 为 Null,我将从 Table1 中获取 Table2 中不存在的所有行。使用您的示例表名,我们将有如下内容:
Select ...
From Person
Left Join Address
On Address.PersonId = Person.Id
Where Address.Id Is Null
【讨论】:
内连接的反面是什么?
一个 OUTER join,可以是三个选项:
This is a good visual representation of JOINs
我想知道地址表中没有行的 Person with bad AddrId 中的行。
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)
【讨论】:
我认为最好的解决方案是使用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 但在 Address 表中没有对应记录的人。
Obs.:在EXISTS查询中使用常量1来避免表访问。
【讨论】:
如果您将内连接视为满足特定条件的两个表的行,那么相反的情况是 either 表中不满足特定条件的行。
例如,以下将选择地址表中具有地址的所有人员:
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)
【讨论】: