只有当另一个连接通过某些条件时才会离开连接表

时间:2013-07-11 21:02:30

标签: sql join left-join ssms

这是我一直遇到的SQL问题! (我使用Sql-Server / sql-management studio)我想离开加入一个表,但只有它通过了需要另一个连接的测试。所以我将B加入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.在我的标题中,我基本上想要连接2个内连接的表...“C.PassesTest上的左连接(b内连接c)”基本上就是我想要做的。

我的两个直接想法两个失败:
1.如果你把PassesTest放在C的连接中,(...左边连接c在B.CID = C.CID和C.PassesTest ...上)你仍然有所有的B记录,你没有想。
2.如果您将测试放在where(如上所述),它会抛出所有未通过的A记录,但我想要那些(因为它是左连接)。

我可以想到2个解决方案,但它们都有点痛苦......真的没有更简单的方法吗?

  1. 加入所有的B / C - 这在逻辑上是我想要的,但显然不是最佳的,因为它在加入之前从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. 进行某种嵌套选择。下面的方式似乎有点多余......也许它可以写得更好

    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 
    
  3. 无论如何,这是我一直遇到的问题,我总是发现自己不得不做一些过于困难的工作!看起来应该有一个更简单的解决方案...或者这只是一个看似困难的SQL问题?

1 个答案:

答案 0 :(得分:2)

您的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子句。


另外,请注意,在您的子查询版本和此示例中,在 加入TableA之前,整个TableB是否必然会加入TableC 。< / p>

SQL被编译为执行计划,优化器有许多选项可以防止这种情况发生。仅仅因为你有这样写的并不意味着RDBMS会盲目地跟随它而不进行优化。