文档章节

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

小强斋太
 小强斋太
发布于 2016/11/09 20:08
字数 1480
阅读 14
收藏 1
点赞 0
评论 0

先从一例子看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的执行顺序)

本文转载自:http://www.cnblogs.com/xqzt/p/4972789.html

共有 人打赏支持
小强斋太
粉丝 0
博文 181
码字总数 0
作品 0
广州
数据库中间件 MyCAT 源码分析 —— 跨库两表Join

摘要: 原创出处 www.iocoder.cn/MyCAT/two-t… 「芋道源码」欢迎转载,保留摘要,谢谢! 本文主要基于 MyCAT 1.6.5 正式版 1. 概述 2. 主流程 3. ShareJoin 3.1 JoinParser 3.2 ShareJoin.pr...

芋道源码掘金Java群217878901
2017/10/03
0
0
postgresql 执行计划理解

首先看下postgresql 执行计划中的一些术语和关键字。 执行计划运算类型 操作说明 是否有启动时间 Seq Scan 扫描表 无启动时间 Index Scan 索引扫描 无启动时间 Bitmap Index Scan 索引扫描 ...

从前
2013/06/05
0
8
MySQL 查询优化器(四)

2.5 LEFT JOIN查询 该测试主要用于测试LEFT JOIN与JOIN的处理逻辑上的差异,具体查询处理逻辑如下所示: JOIN:prepare阶段 setuptables():同2.1测试。 setupfields():同2.1测试。 setupcon...

tara_qri
2015/09/29
37
0
PgSQL · 源码分析 · PG 优化器中的pathkey与索引在排序时的使用

概要 SQL在PostgreSQL中的处理,是类似于流水线方式的处理,先后由: 词法、语法解析,生成解析树后,将其交给语义解析 语义解析,生成查询树,将其交给Planner Planner根据查询树,生成执行...

阿里云RDS-数据库内核组
2017/08/08
0
0
MySQL hints

我们可以对MySQL的对象(表、索引、触发器、自建函数、存储过程等)做注释(comment),这样做的目的是标识该对象的作用等以增强代码的可读性、方便其他同事快速读懂我们写的代码或某个数据库...

大王叫我来巡山Zd
2016/04/11
17
0
数据库性能优化之SQL语句优化2

温馨提示:本篇内容均来自网上,本人只做了稍微处理,未进行细致研究,仅当做以后不备之需,如若你喜欢可尽情转走。 性能不理想的系统中除了一部分是因为应用程序的负载确实超过了服务器的实...

陶邦仁
2012/11/06
0
0
PgSQL · 源码分析 · PG优化器浅析

在使用PostgreSQL数据库过程中,对SQL调优最常用的手段是使用explain查看执行计划,很多时候我们只关注了执行计划的结果而未深入了解执行计划是如何生成的。优化器作为数据库核心功能之一,也...

阿里云RDS-数据库内核组
2016/09/08
0
0
MySQL 查询优化器(总结)

通过以上对单表查询、复合查询不同情况下的查询分析和测试,对查询优化器有了更深入的理解。同时,通过以上测试,也发现很多在查询中应该优化或者规避的策略,这些策略可以有效的优化SQL语句...

tara_qri
2015/09/29
95
0
致sql初学者

很多程序员视 SQL 为洪水猛兽。SQL 是一种为数不多的声明性语言,它的运行方式完全不同于我们所熟知的命令行语言、面向对象的程序语言、甚至是函数语言(尽管有些人认为 SQL 语言也是一种函数...

hello菜bird
2016/02/29
72
0
SQL那些你不知道的事--你的困惑就在这里

很多程序员视 SQL 为洪水猛兽。SQL 是一种为数不多的声明性语言,它的运行方式完全不同于我们所熟知的命令行语言、面向对象的程序语言、甚至是函数语言(尽管有些人认为 SQL 语言也是一种函数...

SuperPcf
2015/11/30
159
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CoreText进阶(七)-添加自定义View和对其

CoreText进阶(七)-添加自定义View和对其 其它文章: CoreText 入门(一)-文本绘制 CoreText入门(二)-绘制图片 CoreText进阶(三)-事件处理 CoreText进阶(四)-文字行数限制和显示更多...

aron1992
10分钟前
0
0
Python爬虫 爬取百合网的女人们和男人们

学Python也有段时间了,目前学到了Python的类。个人感觉Python的类不应称之为类,而应称之为数据类型,只是数据类型而已!只是数据类型而已!只是数据类型而已!重要的事情说三篇。 据书上说...

p柯西
22分钟前
0
0
在Java中,你真的会日期转换吗

1.什么是SimpleDateFormat 在java doc对SimpleDateFormat的解释如下: SimpleDateFormatis a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows fo......

Java小铺
30分钟前
0
0
Linux系统梳理---系统搭建(二):tomcat的安装和使用

上一章讲到JDK的安装使用,这一章主要记录下服务器tomcat的安装以及部署一个项目. 1.下载tomcat,这里下载的是apache-tomcat-8.5.32.tar.gz 2.创建文件夹,便于管理,和JDK一样,在usr目录下创建t...

勤奋的蚂蚁
41分钟前
0
0
ES15-聚合

1.Terms Aggregation 分组聚合 2.Filter Aggregation 过滤聚合

贾峰uk
42分钟前
0
0
【2018.07.19学习笔记】【linux高级知识 20.27-20.30】

20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行命令 20.30 expect脚本传递参数

lgsxp
45分钟前
0
0
10.32/10.33 rsync通过服务同步~10.35 screen工具

通过服务的方式同步要编辑配置文件:[root@linux-xl ~]# vim /etc/rsyncd.confport=873log file=/var/log/rsync.logpid file=/var/run/rsyncd.pidaddress=192.168.43.21[tes...

洗香香
48分钟前
0
0
与女儿谈商业模式 (3):沃尔玛的成功模式

分类:与女儿谈商业模式 | 标签: 经济学 沃尔玛 陈志武 2007-05-10 09:09阅读(11279)评论(30) 与女儿谈商业模式 (3):沃尔玛的成功模式 陈志武 /文 沃尔玛(Wal-Mart)是另一个有意思的财...

祖冲之
54分钟前
0
0
网页加载速度优化方法总结

1、减少请求 最大的性能漏洞就是一个页面需要发起几十个网络请求来获取诸如样式表、脚本或者图片这样的资源,这个在相对低带宽和高延迟的移动设备连接上来说影响更严重。 2、整合资源 对开发...

Jack088
今天
0
0
dubbo学习

https://blog.csdn.net/houshaolin/article/details/76408399

喵五郎
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部