2014-05-21 71 views
0

我想知道它是否總是可能在SQL中通過與子查詢的聯接來考慮條件。舉例來說,如果我有因子子句中的子句

select ... from a join b on ... where p and q 

p僅適用於aqb,則可以我總是改寫爲?

select ... from (select ... from a where p) as a join (select ... from b where q) as b on ... 

謝謝!

[注:1)我使用postgres以防止影響答案。 2)可讀性不是一個重要的考慮因素,因爲這些是自動生成的查詢。 編輯:3)我不僅對內連接感興趣,而且還對其他連接感興趣。]

+0

爲什麼不選擇...從加入b開始(...和q)其中p?我的意思是爲什麼不直接將條件放入連接的ON子句中?當然第一張桌子上的條件必須留在WHERE。使用子查詢可能會阻礙查詢執行優化。 – Frazz

+1

1)把條件放在「上」有什麼區別? 2)如果使用子查詢可能會阻礙優化,那麼我應該嘗試將條件分解出來嗎?我認爲如果條件使得連接的一方小得多,它也可能有助於將因素考慮進去。 – shaunc

+0

將條件加入連接不會影響結果。但是,將單個表中的所有條件放在一個地方可能會有助於優化程序的工作。 – Frazz

回答

1

一般查詢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重新引入。所以這個查詢可能包含前者沒有的行。

1

我會說是的,我想不出一種不可能的情況。凡在它自身可以替換聯接:

select ... from A where x=10 
<=> 
select ... from A join (values (10)) B (x) on A.x = B.x 

也許題外話,但對於一般瓦迪姆Tropashko轉換(http://arxiv.org/abs/cs/0501053)表明,它可以將一組經典的關係代數運算符減少到兩個二進制操作:自然連接和概括工會

+0

感謝您的參考。嗯...所以這也適用於外連接?我也想不出任何事情,但腦海中有一半是對奇怪邊緣案例的回憶。 – shaunc