一般查詢1:
SELECT ...
FROM TableA
JOIN TableB ON <SomeForeignKey>
JOIN TableC ON <SomeForeignKey>
WHERE <SomeConditionOnTableA> AND
<SomeConditionOnTableB> AND
<SomeConditionOnTableC>
...相當於查詢2:
SELECT ...
FROM TableA
JOIN TableB ON <SomeForeignKey> AND <SomeConditionOnTableB>
JOIN TableC ON <SomeForeignKey> AND <SomeConditionOnTableC>
WHERE <SomeConditionOnTableA>
但是,如果不是(INNER)JOIN,而是使用OUTER JOIN,則情況並非如此。與外部連接的等效適用於符合NOT NULL列值,像很簡單的條件:
name='value'
name LIKE '%value%'
number < const
field IN (...)
注意,這些是使外部聯接反正實際意義,因爲它們是過濾掉包含NULL值的行中的所有條件在envolved列...所以他們也會過濾出由OUTER JOIN添加的行,而不是從連接的表中檢索任何東西。
但是,如果您使用OUTER JOIN並開始將列值與NULL進行比較或比較可能導致NULL的表達式,則等價性會中斷。
例如,以該查詢(格式化爲查詢1):
SELECT ...
FROM TableA a
LEFT JOIN TableB b ON <SomeForeignKey>
LEFT JOIN TableC c ON <SomeForeignKey>
WHERE a.somefield = 'whatever'
AND b.name IS NOT NULL
AND c.somenumber >100
在這種情況下,濾波器是具有解決OUTER JOIN之後施加,並且同時消除存在於表B和具有排一個NULL名稱,但也會刪除由OUTER JOIN添加的表中沒有找到匹配行的行。這是不等效到查詢2格式:
SELECT ...
FROM TableA a
LEFT JOIN TableB b ON <SomeForeignKey> AND b.name IS NOT NULL
LEFT JOIN TableC c ON <SomeForeignKey> AND c.somenumber >100
WHERE a.somefield = 'whatever'
在這種情況下解決OUTER前過濾器被應用到表B JOIN。具有NULL名稱的表B行由過濾器消除,但由LEFT JOIN重新引入。所以這個查詢可能包含前者沒有的行。
爲什麼不選擇...從加入b開始(...和q)其中p?我的意思是爲什麼不直接將條件放入連接的ON子句中?當然第一張桌子上的條件必須留在WHERE。使用子查詢可能會阻礙查詢執行優化。 – Frazz
1)把條件放在「上」有什麼區別? 2)如果使用子查詢可能會阻礙優化,那麼我應該嘗試將條件分解出來嗎?我認爲如果條件使得連接的一方小得多,它也可能有助於將因素考慮進去。 – shaunc
將條件加入連接不會影響結果。但是,將單個表中的所有條件放在一個地方可能會有助於優化程序的工作。 – Frazz