这是我一直遇到的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个解决方案,但它们都有点痛苦......真的没有更简单的方法吗?
加入所有的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问题?
答案 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会盲目地跟随它而不进行优化。