2013-07-11 58 views
3

這是我一直遇到的SQL問題! (我使用Sql-Server/sql-management studio)我想要離開連接一個表,但只有當它通過一個需要另一個連接的測試。所以我加入乙到A,但我只是想加入B如果B的加入到表C已通過測試...只有當其他連接通過某些條件時,纔會加入表格

SELECT A.* 
FROM TableA A 
LEFT JOIN TableB B on A.BID = B.BID --only want to join B if C passes the test 
LEFT JOIN TableC C on B.CID = C.CID 
WHERE C.PassesTest -- not correct: throws out records from A that don't pass test 

所以我只是想離開,如果C已通過測試加入B中。在我的標題中,我基本上想要連接兩個內連接的表......「C.PassesTest中的左連接(b內連接C)」基本上就是我想要做的事情。

我立即2個想法都失敗:
1.如果你把PassesTest在加入到C,(...左連接上B.CID = C.CID和C.PassesTest ...... c)您仍然有所有的B記錄掛在你不想要的。
2.如果你把測試放在哪裏(就像上面那樣),它會拋出所有沒有通過的A記錄,但是我想要那些記錄(因爲它是左連接)。

我可以想到2個解決方案,但他們都有點痛苦......難道真的沒有更簡單的方法嗎?

  1. 加入所有B的/ C - 這在邏輯上是我想要什麼,但顯然不是最優的,因爲它是之前參加(所以它的速度慢)

    SELECT A.* 
    FROM TableA A 
    LEFT JOIN (
        SELECT * 
        FROM TableB B 
        INNER JOIN TableC C ON B.CID = C.CID 
        WHERE C.PassesTest 
    ) BC ON BC.BID = A.BID 
    
  2. 抓住從B和C一切
  3. 做一些嵌套選擇。下面的方式似乎有點多餘...也許可以寫一個好一點

    SELECT ABC.StuffFromA FROM (
        SELECT * 
        FROM TableA A 
        LEFT JOIN TableB B on A.BID = B.BID 
        LEFT JOIN TableC C ON B.CID = C.CID 
    ) ABC 
    LEFT JOIN TableB B on ABC.BID = B.BID AND ABC.PassesTest 
    

無論如何,這是我碰到的所有時間,我總是發現自己不得不做一些事情過於困難讓它工作!這似乎應該有一個更簡單的解決方案......或者這只是一個看似棘手的SQL問題?

回答

1

version 1並不需要是一個子查詢,你只需要圍繞INNER JOIN部分() ...

SELECT 
    A.* 
FROM 
    TableA A 
LEFT JOIN 
    (
    TableB B 
    INNER JOIN 
    TableC C 
     ON B.CID = C.CID 
     AND C.PassesTest 
) 
    ON B.BID = A.BID 

我也把你有什麼作爲WHERE從句中的謂語INNER JOIN


此外,要知道,在沒有你的子查詢的版本也不這個例子中,確實被加入到表A之前一定能獲得加入到表C 表B的全部。

SQL被編譯爲一個執行計劃,優化器有很多選項來防止這種情況發生。僅僅因爲你把它寫成這樣,並不意味着RDBMS將盲目地遵循它而不進行優化。

+0

太棒了!我不知道你可以這樣做!感謝一堆:) –

相關問題