zoukankan      html  css  js  c++  java
  • 从join on和where执行顺序认识T-SQL查询处理执行顺序

    先从一例子看join on 和 where执行结果的不同

    CREATE TABLE "SCOTT"."A" (
    
    "PERSON_ID" NUMBER(5) NULL ,
    
    "PERSON_NAME" VARCHAR2(255 BYTE) NULL 
    
    )
    
    ;
    
    -- ----------------------------
    
    -- Records of A
    
    -- ----------------------------
    
    INSERT INTO "SCOTT"."A" VALUES ('1', '张三');
    
    INSERT INTO "SCOTT"."A" VALUES ('2', '李四');
    
    INSERT INTO "SCOTT"."A" VALUES ('3', '王五');
    
    INSERT INTO "SCOTT"."A" VALUES ('4', '赵六');
    
    INSERT INTO "SCOTT"."A" VALUES ('5', '周七');
    
    CREATE TABLE "SCOTT"."B" (
    
    "PERSON_ID" NUMBER(5) NULL ,
    
    "LOVE_FRUIT" VARCHAR2(255 BYTE) NULL 
    
    );
    
    -- ----------------------------
    
    -- Records of B
    
    -- ----------------------------
    
    INSERT INTO "SCOTT"."B" VALUES ('1', '香蕉');
    
    INSERT INTO "SCOTT"."B" VALUES ('2', '苹果');
    
    INSERT INTO "SCOTT"."B" VALUES ('3', '橘子');
    
    INSERT INTO "SCOTT"."B" VALUES ('4', '');
    
    INSERT INTO "SCOTT"."B" VALUES ('8', '');
    View Code

    查询语句1

    SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1;

    clip_image001

    查询语句2

    SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID WHERE A.PERSON_ID=1;

    clip_image002

     为什么结果不同呢? 可以从查询逻辑处理的过程解释。

    select语句的处理过程

    我们知道,SQL 查询的大致语法结构如下:

    (5)SELECT DISTINCT TOP(<top_specification>) <select_list>                     
    
    (1)FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate>
    
    (2)WHERE <where_predicate>
    
    (3)GROUP BY <group_by_specification>
    
    (4)HAVING <having_predicate>
    
    (6)ORDER BY <order_by_list>

    select 语法的处理顺序

    The following steps show the processing order for a SELECT statement.

    1. FROM
    2. ON
    3. JOIN
    4. WHERE
    5. GROUP BY
    6. WITH CUBE or WITH ROLLUP
    7. HAVING
    8. SELECT
    9. DISTINCT
    10. ORDER BY
    11. TOP

    这些步骤执行时, 每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只是最后一步生成的表才会返回给调用者。如果没有在查询中指定某一子句,将跳过相应的步骤。

    select各个阶级分别干了什么:

    (1)FROM 阶段

        FROM阶段标识出查询的来源表,并处理表运算符。在涉及到联接运算的查询中(各种join),主要有以下几个步骤:

          a.求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(cross join),求笛卡儿积,生成虚拟表VT1-J1。

          b.ON筛选器。这个阶段对上个步骤生成的VT1-J1进行筛选,根据ON子句中出现的谓词进行筛选,让谓词取值为true的行通过了考验,插入到VT1-J2。

          c.添加外部行。如果指定了outer join,还需要将VT1-J2中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。

    经过以上步骤,FROM阶段就完成了。概括地讲,FROM阶段就是进行预处理的,根据提供的运算符对语句中提到的各个表进行处理(除了join,还有apply,pivot,unpivot)

    (2)WHERE阶段

         WHERE阶段是根据<where_predicate>中条件对VT1中的行进行筛选,让条件成立的行才会插入到VT2中。

    (3)GROUP BY阶段

          GROUP阶段按照指定的列名列表,将VT2中的行进行分组,生成VT3。最后每个分组只有一行。

    (4)HAVING阶段

    该阶段根据HAVING子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到VT4中。

    (5)SELECT阶段

    这个阶段是投影的过程,处理SELECT子句提到的元素,产生VT5。这个步骤一般按下列顺序进行

            a.计算SELECT列表中的表达式,生成VT5-1。

            b.若有DISTINCT,则删除VT5-1中的重复行,生成VT5-2

            c.若有TOP,则根据ORDER BY子句定义的逻辑顺序,从VT5-2中选择签名指定数量或者百分比的行,生成VT5-3

    (6)ORDER BY阶段

    根据ORDER BY子句中指定的列明列表,对VT5-3中的行,进行排序,生成游标VC6.

    例子解释

    查询语句1的执行过程

    SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1;

     

    求笛卡尔积,产生5*5=25条记录

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

    1

    张三

    2

    苹果

    1

    张三

    3

    橘子

    1

    张三

    4

    1

    张三

    8

    2

    李四

    1

    香蕉

    2

    李四

    2

    苹果

    2

    李四

    3

    橘子

    2

    李四

    4

    2

    李四

    8

    3

    王五

    1

    香蕉

    3

    王五

    2

    苹果

    3

    王五

    3

    橘子

    3

    王五

    4

    3

    王五

    8

    4

    赵六

    1

    香蕉

    4

    赵六

    2

    苹果

    4

    赵六

    3

    橘子

    4

    赵六

    4

    4

    赵六

    8

    5

    周七

    1

    香蕉

    5

    周七

    2

    苹果

    5

    周七

    3

    橘子

    5

    周七

    4

    5

    周七

    8

     

     

    ON筛选器(A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1)

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

     

     

    添加外部行

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

    1

    张三

     

     

    1

    张三

     

     

    1

    张三

     

     

    1

    张三

     

     

     


    查询语句2的执行过程

    SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID WHERE A.PERSON_ID=1;

     

     

    求笛卡尔积,产生5*5=25条记录

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

    1

    张三

    2

    苹果

    1

    张三

    3

    橘子

    1

    张三

    4

    1

    张三

    8

    2

    李四

    1

    香蕉

    2

    李四

    2

    苹果

    2

    李四

    3

    橘子

    2

    李四

    4

    2

    李四

    8

    3

    王五

    1

    香蕉

    3

    王五

    2

    苹果

    3

    王五

    3

    橘子

    3

    王五

    4

    3

    王五

    8

    4

    赵六

    1

    香蕉

    4

    赵六

    2

    苹果

    4

    赵六

    3

    橘子

    4

    赵六

    4

    4

    赵六

    8

    5

    周七

    1

    香蕉

    5

    周七

    2

    苹果

    5

    周七

    3

    橘子

    5

    周七

    4

    5

    周七

    8

     

     

    ON筛选器  (A.PERSON_ID=B.PERSON_ID )

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

    2

    李四

    2

    苹果

    3

    王五

    3

    橘子

    4

    赵六

    4

     

     

    添加外部行

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

    2

    李四

    2

    苹果

    3

    王五

    3

    橘子

    4

    赵六

    4

    5

    周七

     

     

     

     

    WHERE阶段 (A.PERSON_ID=1)

     

     

    A.PERSON_ID

    PERSON_NAME

    B.PERSON_ID

    LOVE_FRUIT

    1

    张三

    1

    香蕉

     



    有了上面的验证,我们可以猜测下面语句的执行结果

    SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID

    image

    参考文献

    从join on和where执行顺序认识T-SQL查询处理执行顺序

    https://msdn.microsoft.com/en-us/library/ms189499%28v=SQL.100%29.aspx

    sql(join on 和where的执行顺序)

  • 相关阅读:
    【Python 开发】第三篇:python 实用小工具
    【Python 开发】第二篇 :Python安装
    【Linux 运维】 安装PHP工具Composer
    【shell 每日一练6】初始化安装Mysql并修改密码
    【zabbix 监控】第三章 创建主机组和主机
    【Docker】第一篇 Docker的初始化安装部署
    【shell 练习5】编写简单的多级菜单
    【zabbix 监控】第二章 安装测试被监控主机
    【zabbix 监控】第一章 zabbix的安装配置
    1数组和字符串题解
  • 原文地址:https://www.cnblogs.com/xqzt/p/4972789.html
Copyright © 2011-2022 走看看