2013-07-11 33 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

太棒了!我不知道你可以这样做!感谢一堆:) –

相关问题