考虑此查询
select *
from documents d
where exists (select 1 as [1]
from (
select *
from (
select *
from ProductMediaDocuments
where d.id = MediaDocuments_Id
) as [dummy1]
) as [s2]
where exists(
select *
from ProductSkus psk
where psk.Product_Id = s2.MediaProducts_Id
)
)
有人能告诉我SQL Server是如何处理的吗?当语句出现在括号中时,这意味着它将首先执行。但这是否也适用于上述声明?在这种情况下,我不这么认为,因为子查询需要外部查询的值。那么,这是如何在幕后工作的?
答案 0 :(得分:2)
这完全取决于数据库引擎。
由于SQL是一种声明性语言,您可以指定所需的 WHAT ,但 HOW 部分取决于数据库引擎,它实际上取决于索引存在等诸多因素,类型,碎片;行基数,统计。
这只是少数几个,因为列表可以继续。
当然,您可以查看执行计划,但重点是您无法知道 HOW 只会在阅读查询时执行。
答案 1 :(得分:0)
我简化了你的代码。
SELECT *
FROM documents d
WHERE EXISTS ( SELECT 1
FROM ProductMediaDocuments s2
WHERE d.id = MediaDocuments_Id
AND EXISTS (
SELECT *
FROM ProductSkus psk
WHERE psk.Product_Id = s2.MediaProducts_Id
)
)
答案 2 :(得分:0)
执行计划将告诉您引擎实际执行的操作。也就是物理处理顺序。 AFAIK,查询计划程序将重写您的查询,如果它找到更好的方式来表达它自己或引擎。如果您的问题是,"为什么我的查询不按我认为应该的方式工作。"那就是你应该开始的地方。
它也有这个说明:
[previous]步骤显示SELECT语句的逻辑处理顺序或绑定顺序。此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。例如,如果查询处理器可以绑定(访问)FROM子句中定义的表或视图,则这些对象及其列可供所有后续步骤使用。相反,因为SELECT子句是步骤8,所以前面的子句不能引用该子句中定义的任何列别名或派生列。但是,它们可以由后续子句引用,例如ORDER BY子句。请注意,语句的实际物理执行由查询处理器确定,并且顺序可能与此列表不同。
FROM
将包括内联视图(子查询)或CTE别名。每次找到子查询时,它应该从头开始并评估该查询。
答案 3 :(得分:0)
我认为这段代码更清楚,不是吗?
SELECT d.*
FROM documents d
JOIN ProductMediaDocuments s2 ON d.id = MediaDocuments_Id
JOIN ProductSkus psk ON psk.Product_Id = s2.MediaProducts_Id