我有一些 T-SQL 难题似乎正在起作用,但我想知道是否有人可以尝试向我详细说明这里发生的事情。考虑以下脚本:
SELECT *
FROM TableA a
WHERE a.CustomerID NOT IN (SELECT b.CustomerID FROM TableB b WHERE a.CustomerID = b.CustomerID AND a.WorkOrder = b.WorkOrder)
AND a.[Date] > DATEADD(DD,-3,GETDATE())
我很困惑编译器如何不会在这个脚本上内爆。它如何在引用外部查询的子查询上选择 where NOT IN?获取 TableA 的内容,其中 CustomerID NOT IN CustomerID 来自 TableB 等...但是当它在子查询中找到匹配的 CustomerID 时,NOT IN 会启动并阻止记录显示在外部查询选择中。我猜这是编译器停止的地方。但是因为没有选择那个特定的CustomerID,它不能加入内部查询,因此内部查询不选择那个CustomerID,然后允许外部查询选择该记录?是的?不?掉进兔子洞?有没有更好的方法来写这个?
如果有人可以详细说明这里发生的事情,或参考可以解释的内容,我们将不胜感激。我真的找不到任何人解释这个过程,也许没有使用正确的搜索词。
谢谢!
它被称为“相关子查询”和“子查询可以为外部查询处理的每一行评估一次”。
所以在这里,对于 TableA 的每一行,子查询从 TableB 中寻找匹配的数据,并确定是否满足 NOT IN 条件。然后到 TableA 中的下一行重复该循环,直到 TableA 的所有相关行都被评估。
当您连接 2 个表但忽略存在连接的行时,另一种方法可能是“左排除连接”。
SELECT
*
FROM TableA a
LEFT JOIN TableB b ON a.CustomerID = b.CustomerID
AND a.WorkOrder = b.WorkOrder
WHERE b.CustomerID IS NULL
AND a.[Date] > DATEADD(DD, -3, GETDATE())
;
或使用 NOT EXISTS 的另一种“半连接”替代方案:
SELECT
*
FROM TableA a
WHERE NOT EXISTS (
SELECT NULL
FROM TableB b
WHERE a.CustomerID = b.CustomerID
AND a.WorkOrder = b.WorkOrder
)
AND a.[Date] > DATEADD(DD, -3, GETDATE())
;
注意用于 |NOT| 的子查询 EXISTS 不必通过 select 子句返回任何值。有些人在使用 EXISTS 时更喜欢使用“select 1”或“select *”,但实际上使用哪个并不重要。使用“select NULL”是我的偏好。
您可以通过检查执行计划来了解有关这些替代方案的更多信息,例如,请参见http://sqlfiddle.com/#!6/04064/2。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句