我读到,CROSS APPLY就像 JOIN.. 我认为 JOIN 也可以通过 EXISTS 完成(相关子查询)
我很困惑,使用 CROSS APPLY 和 EXISTS 有什么区别?
我什么时候应该针对 EXISTS 进行 CROSS APPLY?
我读到,CROSS APPLY就像 JOIN.. 我认为 JOIN 也可以通过 EXISTS 完成(相关子查询)
我很困惑,使用 CROSS APPLY 和 EXISTS 有什么区别?
我什么时候应该针对 EXISTS 进行 CROSS APPLY?
CROSS APPLY 不仅仅是一个 JOIN。JOIN 在两组数据之间查找匹配(或不匹配)的行。CROSS APPLY 是一种针对您应用它的事物的每一行运行查询的方法。这可以作为一种过滤机制,类似于 JOIN 的工作方式,但它对每一行都应用了一些东西,所以需要这样考虑。
子查询中的 EXISTS 是一种完全不同的过滤机制。这是一种快速识别的方法,因为当它发现某些东西时,它会立即短路它的搜索。一般而言,您希望使用 EXISTS 的地方是您可能会在过滤条件上获得成功,从而使搜索尽可能短。但是,EXISTS 不会找到所有匹配项。它只是找到第一个匹配项,然后停止搜索。
因此,虽然您可以通过这三种不同的方法获得相同的结果,但按照定义使用它们,您通常是对的。如果您实际上是在连接两组数据,请使用 JOIN。如果要针对数据集中的每一行运行一个进程,通常是一个过滤器,请使用 CROSS APPLY。如果您想对可能的正匹配进行快速过滤,请使用 EXISTS。
格兰特的回应是正确的但从个人风格的角度来看,我只使用 OUTER APPLY。这是一个常见的模式,所有这三个都做同样的事情,但是通过使用外部应用,验证时您可以简单地注释掉“WHERE ca2.HasAddress = 'Yes'”并将 ca2.HasAddress 添加到主选择以验证您的过滤器正在删除您想要的记录,而其他两种过滤方法在行级别不提供相同的透明度。
SELECT c.CustomerID
FROM SalesLT.Customer c
OUTER APPLY (SELECT TOP 1 'Yes' HasAddress
FROM SalesLT.CustomerAddress ca
WHERE c.CustomerID = ca.CustomerID)
ca2
WHERE ca2.HasAddress = 'Yes'
SELECT c.CustomerID
FROM SalesLT.Customer c
CROSS APPLY (SELECT TOP 1 'Yes' HasAddress
FROM SalesLT.CustomerAddress ca
WHERE c.CustomerID = ca.CustomerID)
ca2
SELECT c.CustomerID
FROM SalesLT.Customer c
WHERE EXISTS (SELECT 1
FROM SalesLT.CustomerAddress ca
WHERE c.CustomerID = ca.CustomerID)