sql – 仅当另一个连接通过某些条件时才使用左连接表

这是我一直遇到的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.在我的标题中,我基本上想要连接两个内部连接的表……“C.PassesTest上的左连接(b内连接c)”基本上就是我想要做的.

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

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

>加入所有的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

>做一些嵌套选择.下面的方式似乎有点多余……也许它可以写得更好一些

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不需要是子查询,只需要在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.

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

点赞