假设我们有以下表结构:
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
PersonId | Name | AddressId | PersonId
1 | John Doe | NULL | NULL
2 | Jane Doe | NULL | NULL
VS
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
为什么查询会返回不同的结果?
答案 0 :(得分:2)
第一个查询不符合您的任何条件。因此,它显示@Person
表(典型Left join
)的所有结果。在第二个查询中,where
子句应用于join
之后。因此它显示了正确的结果。
答案 1 :(得分:1)
首先:
从Person
获取所有记录(两个)并加入来自0
的{{1}}个记录,因为没有任何地址有Address
。之后,不会应用其他过滤器。你会看到来自PersonID = NULL
第二
从Person
获取所有记录(两个),其中一个记录加入Person
Address
。之后,我们应用了ID = 1
过滤器,其中一个已加入WHERE
的记录消失了。
答案 2 :(得分:0)
ON子句定义从两个表中显示的所有匹配行。 WHERE子句实际上过滤了行。
在第一个查询中,它返回2行,因为LEFT JOIN返回左表中的所有行,而不管右表中的匹配。
第二个查询返回1行,因为对于PersonId = 1,@ Address表包含匹配的记录,因此a.PersonId为NOT NULL。
答案 3 :(得分:0)
养成从Where
条件读取SQL查询的习惯,然后查看joins
,这将使您更清楚地了解/了解正在发生或将要返回的内容。
在这种情况下,您说WHERE a.PersonId IS NULL
必须发生Select
部分,并且必须Join
使用以下join
条件。
这就是您的计算机正在读取您的查询的结果,因此会产生不同的结果集。
然后相反,在没有where子句的情况下,左表(p)上的结果不必存在于(a)上,但同时(a)上的结果必须为null但他们可能已经不存在了。在这一点上,你的SQL将会被混淆。