過濾條件差異 - Where 子句與加入條件
快速簡單的過濾問題。
輸出會有什麼差異,或者它將過濾條件從 WHERE 子句移到 Join 條件中會有什麼影響。
例如:
Select a1.Name, a2.State from student a1 left join location a2 on a1.name_id = a2.name_id where a1.name LIKE 'A%' and a2.state = 'New York';
對此:
Select a1.Name, a2.State from student a1 left join location a2 on (a1.name_id = a2.name_id) and a2.state = 'New York' where a1.name LIKE 'A%';
謝謝大家。
將顯示以“A”開頭且位置在紐約的學生姓名。
將顯示所有以“A”開頭的學生姓名,如果學生所在州是紐約,則顯示“紐約”,或者在其他情況下為空(沒有對應的州,或者學生所在州不是紐約)
(1) 和 (2) 之間的區別 - (1) 不會有非紐約學生。
@a1ex07 的答案是完全正確的。但是,讓我們提供一個更籠統的答案。
當你有一個
TableA a LEFT JOIN TableB b
場景時,你必須小心你如何在你的子句中使用TableB
欄位。WHERE
對於 中
TableA
沒有匹配行的任何行TableB
,所有欄位TableB
都將設置為 NULL。讓我們看看你的例子。
我們假設您希望 ( ) 中的所有行在
TableA
(student
) 中沒有匹配的行,或者TableB
在(location
)中具有匹配的行,其中( ) 等於“紐約”。TableB``b.Column1``location.State
- 如果您的
WHERE
子句包含對TableB
不允許在該欄位中使用 NULL 值的欄位的檢查,則將排除所有TableA
沒有匹配行的行。TableB
範例:
WHERE b.State = 'New York'
-TableA
沒有匹配TableB
行的行將具有B.Column1
NULL。由於NULL = 'New York'
不是 TRUE,因此沒有匹配( ) 行的TableA
( ) 行都不符合子句中的條件。student``TableB``location``WHERE
實際上,這使得
LEFT JOIN
anINNER JOIN
. 2. 如果您確實允許TableB
值為 NULL,則需要注意不要允許輸入比您的意思更多的值。如果將上述範例
WHERE
子句更改為:WHERE (b.State = 'New York' OR b.State IS NULL)
然後仍將包括
TableA
沒有匹配行的行。TableB
但是,具有匹配TableA
行且設置為 NULL 的行也是如此(在您的情況下,具有匹配行的行,其中為 NULL)。這可能不是本意。TableB``Column1``student``location``location.State
3. 要真正滿足我們假設的意圖,您至少有兩種選擇:
- 首先,您可以對條件
TableB
中的行進行限制JOIN
:FROM TableA a LEFT JOIN TableB b ON (a.name_id = b.name_id AND b.State = 'New York')
允許通過沒有匹配( ) 行的所有`TableA`( ) 行;如果有*匹配*的行,匹配的行來自並且僅當是“紐約”時才會被包括在內。`student``TableB``location``TableB``TableA``TableB``b.State` 其次,在`WHERE`子句中包含您的檢查,但使用`JOIN`in 列`TableB`允許 NULL:
OM TableA a FT JOIN TableB b ON (a.name_id = b.name_id) ERE (b.State = 'New York' OR b.name_id IS NULL)
假定`a.name_id`不能為 NULL。然後,唯一的方法`b.name_id`可以是 NULL 是如果沒有找到匹配的`JOIN`in `TableB`。同樣,`TableA`不`TableB`匹配的行也包括在內(因為`b.name_id`這些行總是為 NULL)。根據我們的假設,where`TableA`有一個匹配的`TableB`行,`b.name_id`永遠*不會*是 NULL,因此`b.State` *必須*是“New York”才能包含匹配`TableA`的`TableB`行對。