2017-02-21 92 views
0

如果我有這個疑問:MYSQL - 使用並在JOIN與WHERE子句

select * from tableA 
left outer join tableB on tableA.id=tableB.id 
AND tableB.foo = 1 
where tableA.owner=10 

我獲得了29倍的結果,但如果我動議進入WHERE子句,如:

select * from tableA 
left outer join tableB on tableA.id=tableB.id 
where tableA.owner=10 
AND tableB.foo = 1 

我那麼只能得到17個結果。

我查看了所有內容,無法找到關於在JOIN和WHERE子句中如何使用AND的不同方法的權威指南。任何人都可以向我解釋這個嗎?

此外,如果我在JOIN中執行類似AND tableB.foo = NULL的所有操作,即使表中的值不爲空,我的所有tableB.foo字段在查詢結果中都爲NULL。在通過WHERE子句過濾之前,在JOIN子句中使用AND是否會更改FROM選擇中的該字段?

+0

您可以在此處看到:http://stackoverflow.com/a/15706298/7416478 –

回答

1

您加入外表的所有條件都應該在JOIN子句中(如您的第一個查詢)。將它放在WHERE子句中(如您的第二個查詢)將OUTER JOIN隱式轉換爲INNER JOIN

至於你的問題AND tableB.foo = NULL這是不正確的MySQL語法。 NULLs需要special treatment,使用像IS NULL這樣的運算符。您應該使用AND tableB.foo IS NULL

1

外連接與內連接的連接方式相同。另外,當沒有匹配記錄時,所有列設置爲空的虛擬記錄被加入(所以你仍然從結果中的第一個表中獲得行)。

在您的第一個查詢中,您正在查找具有相同ID和foo = 1的tableB中的匹配項。對於沒有這種匹配的tableA中的記錄,您仍然得到一個結果行(所有tableA字段爲空)。

在第二個查詢中,您在tableB中查找具有相同ID的匹配項。對於沒有這種匹配的tableA中的記錄,您仍然會得到一個結果行(所有tableA字段爲空)。然後在你的where子句中,你只保留foo = 1的行。這就消除了所有外連接的記錄(因爲它們的foo爲null),你就是你將要使用普通內連接的地方。

因此,請始終將所有條件放在ON子句中的外連接表上。 (雖然有一個例外;反加入,但您可以再次學習該模式。)