从 join on 和 where 执行顺序认识T-sql查询执行顺序

本文深入探讨了SQL查询的执行顺序,以LEFT JOIN为例,解释了不同的WHERE子句位置如何影响查询结果。在LEFT JOIN中,WHERE子句的位置决定了筛选条件的处理时机,从而导致结果集的不同。理解这一原理对于优化SQL查询至关重要。
摘要由CSDN通过智能技术生成

示例代码

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', '桃');
1.join on
SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1;

在这里插入图片描述

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

在这里插入图片描述

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


SQL执行顺序

(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>

(5)SELECT DISTINCT TOP(<top_specification>) <select_list>  

(6)ORDER BY <order_by_list>
  • FROM
  • ON
  • JOIN
  • WHERE
  • GROUP BY
  • WITH CUBE or WITH ROLLUP
  • HAVING
  • SELECT
  • DISTINCT ORDER BY 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.join on 执行过程
SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1;

求笛卡尔积,产生5*5=25条记录
在这里插入图片描述
ON筛选器(A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1)
在这里插入图片描述
添加外部行
在这里插入图片描述

2.where执行过程
SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID WHERE A.PERSON_ID=1;

求笛卡尔积,产生5*5=25条记录
在这里插入图片描述
ON筛选器 (A.PERSON_ID=B.PERSON_ID )
在这里插入图片描述
添加外部行
在这里插入图片描述
WHERE阶段 (A.PERSON_ID=1)
在这里插入图片描述

3.下面这条sql的执行结果
SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID=B.PERSON_ID

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值