2016-07-07 143 views
1

假設我們有如下表結構:左加入含where子句INSIDE加入

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 

爲什麼查詢返回不同的結果?

+1

它變成了一個內部聯接:http://stackoverflow.com/questions/3256304/left-join-turns-into-inner-join –

+0

因爲PersonID上的'LEFT JOIN'確實產生了一個匹配,並且PersonID不爲NULL那一排。 –

回答

2

第一個查詢不符合您的任何條件。因此它顯示@Person表(典型的Left join)的所有結果。在第二個查詢中,where子句應用於join之後。因此顯示正確的結果。

1

第一:

得到所有記錄Person(二),從Address加入0記錄,COS沒有地址的有PersonID = NULL。之後,沒有應用其他過濾器。你從Person

其次看到兩個記錄:

得到的所有記錄(二)從Person,其中一個連接到AddressID = 1。之後,您的WHERE篩選器已應用,並且加入ID = 1的記錄之一消失。

0

ON子句定義從兩個表中顯示的所有匹配行。 WHERE子句實際上是對行進行過濾。

在第一個查詢中,它返回2行,因爲LEFT JOIN返回左表中的所有行,與來自右表的匹配無關。

第二個查詢返回1行,因爲對於PersonId = 1,@Address表包含匹配的記錄,因此a.PersonId不爲NULL。

0

讓它習慣於從Where條件中讀取您的SQL查詢,然後看看您的joins,這會讓您更清楚地瞭解正在發生或將要返回的內容。

在這種情況下,你說WHERE a.PersonId IS NULLSelect部分必須發生,它必須Join使用以下join條件。

這就是您的查詢正在被您的機器讀取的方式,因此有不同的結果集。

然後相反,在沒有where子句的情況下,左表(p)上的結果不必存在於(a)上,但同時(a)上的結果必須是爲空但已經可能不存在。在這一點上,你的SQL會感到困惑。