这是我一直遇到的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会盲目地跟随它而不进行优化.