Sql server 在联接中包含where子句的左联接
假设我们有以下表格结构:Sql server 在联接中包含where子句的左联接,sql-server,Sql Server,假设我们有以下表格结构: DECLARE @Person TABLE ( PersonId INT, Name VARCHAR(50) ) DECLARE @Address TABLE ( AddressId INT IDENTITY(1,1), PersonId INT ) 我们插入两个人的记录: INSERT INTO @Person (PersonId, Name) VALUES (1, 'John Doe') INSERT INTO @Person (
DECLARE @Person TABLE
(
PersonId INT,
Name VARCHAR(50)
)
DECLARE @Address TABLE
(
AddressId INT IDENTITY(1,1),
PersonId INT
)
我们插入两个人的记录:
INSERT INTO @Person (PersonId, Name) VALUES (1, 'John Doe')
INSERT INTO @Person (PersonId, Name) VALUES (2, 'Jane Doe')
但是我们只为John
INSERT INTO @Address (PersonId) VALUES (1)
如果我执行以下查询,我会得到不同的结果
SELECT *
FROM @Person p
LEFT JOIN @Address a
ON p.PersonId = a.PersonId AND a.PersonId IS NULL
VS
为什么查询返回不同的结果?第一个查询不符合您的任何条件。因此,它显示了
@Person
表中的所有结果(典型的左连接
)。其中,与第二个查询一样,Where
子句应用于join
之后。因此,它显示了正确的结果。首先:
从Person
获取所有记录(两个),并从Address
加入0
记录,因为地址中没有PersonID=NULL
。之后,不再应用其他过滤器。您可以看到Person
第二:
从
Person
获取所有记录(两条),其中一条记录以ID=1加入到Address
。在此之后,您的WHERE
过滤器将被应用,并且其中一个joinedID=1的记录将消失。ON子句定义了要从两个表中显示的所有匹配行。
WHERE子句实际上过滤行
在第一个查询中,它返回2行,因为LEFT JOIN返回左表中的所有行,而不考虑右表中的匹配
第二个查询返回1行,因为对于PersonId=1,@Address表包含匹配的记录,因此a.PersonId不为NULL 养成习惯,从Where
条件中读取SQL查询,然后查看连接,这将使您对正在发生或将要返回的内容有更清晰的含义/理解
在这种情况下,您所说的中a.PersonId为NULL
必须出现选择
部分,并且必须使用以下加入
标准加入
这就是机器读取查询的方式,因此会产生不同的结果集
相反,在没有where子句的情况下,左表(p)上的结果不必存在于(a)上,但同时(a)上的结果必须为null,但可能已经不存在了。此时您的SQL已经被搞糊涂了。它变成了一个内部联接:因为personID上的左联接确实产生了一个匹配项,并且personID在该行中不为NULL。
PersonId | Name | AddressId | PersonId
1 | John Doe | NULL | NULL
2 | Jane Doe | NULL | NULL
SELECT *
FROM @Person p
LEFT JOIN @Address a
ON p.PersonId = a.PersonId
WHERE a.PersonId IS NULL
PersonId | Name | AddressId | PersonId
2 | Jane Doe | NULL | NULL