它执行第一个WHERE子句或JOIN子句

时间:2015-06-10 07:33:22

标签: sql sql-server select join where

哪个子句首先在SELECT语句中执行?

我在此基础上对select查询有疑问。

考虑以下示例

SELECT * 
FROM #temp A 
INNER JOIN #temp B ON A.id = B.id 
INNER JOIN #temp C ON B.id = C.id 
WHERE A.Name = 'Acb' AND B.Name = C.Name
  1. 是否,首先检查WHERE子句然后执行INNER JOIN

  2. 首先JOIN然后检查条件?

  3. 如果它首先执行JOIN然后WHERE条件;如何在不同JOIN s的条件下执行更多?

5 个答案:

答案 0 :(得分:16)

查询处理的概念顺序是:

$('footer').css('height', '300px');

但这只是一个概念性的顺序。事实上,引擎可能会决定重新安排条款。这是证据。让我们制作2个表,每个表1000000行:

1. FROM
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. ORDER BY

现在运行2个查询:

CREATE TABLE test1 (id INT IDENTITY(1, 1), name VARCHAR(10))
CREATE TABLE test2 (id INT IDENTITY(1, 1), name VARCHAR(10))


;WITH cte AS(SELECT -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) d FROM
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t1(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t2(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t3(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t4(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t5(n) CROSS JOIN
(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t6(n))

INSERT INTO test1(name) SELECT 'a' FROM cte

注意首先会在SELECT * FROM dbo.test1 t1 JOIN dbo.test2 t2 ON t2.id = t1.id AND t2.id = 100 WHERE t1.id > 1 SELECT * FROM dbo.test1 t1 JOIN dbo.test2 t2 ON t2.id = t1.id WHERE t1.id = 1 条件下过滤大多数行,在join条件下过滤第二行。看看制作的计划:

  

1 TableScan - 谓词:[测试]。[dbo]。[test2]。[id] as [t2]。[id] =(100)

     

2 TableScan - 谓词:[测试]。[dbo]。[test2]。[id] as [t2]。[id] =(1)

这意味着在优化的第一个查询中首先决定评估where条件以过滤掉行,然后在第二个中首先评估join子句。

答案 1 :(得分:8)

查询处理阶段的逻辑顺序是:

  1. FROM - 包括JOIN s
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY
  7. 即使在JOINWHERE条款中,您也可以拥有尽可能多的条件。像:

    Select * from #temp A 
    INNER JOIN #temp B ON A.id = B.id AND .... AND ... 
    INNER JOIN #temp C ON B.id = C.id AND .... AND ...
    Where A.Name = 'Acb'
    AND B.Name = C.Name
    AND ....
    

答案 2 :(得分:3)

您可以参考MSDN

  

查询选择的行首先由FROM子句过滤   连接条件,然后WHERE子句搜索条件,然后   HAVING子句搜索条件。 可以在中指定内部联接   FROM或WHERE子句,不影响最终结果。

您还可以在执行查询之前使用SET SHOWPLAN_ALL ON来显示查询的执行计划,以便您可以衡量两者的性能差异。

答案 3 :(得分:1)

您可以参考此join optimization

SELECT * FROM T1 INNER JOIN T2 ON P1(T1,T2)
                 INNER JOIN T3 ON P2(T2,T3)
  WHERE P(T1,T2,T3)

嵌套循环连接算法将以下列方式执行此查询:

FOR each row t1 in T1 {
  FOR each row t2 in T2 such that P1(t1,t2) {
    FOR each row t3 in T3 such that P2(t2,t3) {
      IF P(t1,t2,t3) {
         t:=t1||t2||t3; OUTPUT t;
      }
    }
  }
}

答案 4 :(得分:0)

如果您来到此网站来解答有关logical query processing的问题,那么您确实需要阅读this article on ITProToday by Itzik Ben-Gan

Figure 3: Logical query processing order of query clauses

1 FROM 
2 WHERE 
3 GROUP BY 
4 HAVING 
5 SELECT
    5.1 SELECT list
    5.2 DISTINCT
6 ORDER BY 
7 TOP / OFFSET-FETCH