具有子查询的查询的执行顺序是什么?

时间:2015-04-30 16:08:52

标签: tsql

考虑此查询

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是如何处理的吗?当语句出现在括号中时,这意味着它将首先执行。但这是否也适用于上述声明?在这种情况下,我不这么认为,因为子查询需要外部查询的值。那么,这是如何在幕后工作的?

4 个答案:

答案 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,查询计划程序将重写您的查询,如果它找到更好的方式来表达它自己或引擎。如果您的问题是,"为什么我的查询不按我认为应该的方式工作。"那就是你应该开始的地方。

文档说logical processing order是:

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE或WITH ROLLUP
  7. HAVING
  8. 选择
  9. DISTINCT
  10. ORDER BY
  11. TOP
  12. 它也有这个说明:

      

    [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