mysql where条件执行顺序_资深DBA整理MySQL基础知识四:大神们都忽略的SQL语句执行的顺序...

前几篇说了一些SQL语句的基础知识,SQL语句也是一种编程语言,语言执行是有顺序的。在学习SQL语言的时候一定要知道他执行的顺序,这样才能能好的理解SQL,学好SQL。下面进入正题,先放两张图。

08d5d48c43a62eba393d19d2ae802841.png

图一

7a4fc5e5e30a242b55f59807e8cb0f0b.png

图二

从上图的顺序中我们不难看出,所有的查询语句都是从from开始执行的,在整个执行过程中,每个有步的执行都会为下一个步生成一个虚拟表,这个虚拟表将作为下一个执行的输入。

以下步骤结合图一和图二去理解

第一步:

首先对from子句中的前两个表执行一个笛卡尔乘积,此时生成虚拟表 vt1(图一), 接下来便是应用on筛选器,on 中的逻辑表达式将应用到 vt1 中的各个行,筛选出满足on逻辑表达式的行,生成虚拟表 vt2

第二步:

如果是 join 那么这一步就将添加外部行,left jion 就把左表在第一步中on过滤的添加进来,如果是right join 那么就将右表在第y一步中的on过滤掉的行添加进来,这样生成虚拟表 vt3 ,如果 from 子句中的表数目多余两个表,那么就将vt3和第三个表连接从而计算笛卡尔乘积,生成虚拟表,该过程就是一个重复1-2的步骤,最终得到一个新的虚拟表 vt3。

第三步:

应用where筛选器,对上一步生产的虚拟表引用where筛选器,生成虚拟表vt4。

关于在where和on作为筛选的区别在这里也简单的说一下,我们要是知道on和where运行的时间,就能够很轻松的理解这两者的区别。比如一张左连接关联的表,on 条件是在生成临时表vt2时使用的条件,它不管on中条件是否为真,都会返回左表中的记录。而where条件是在临时表vt2生成好后,在对临时表vt2进行过滤,这时候与表是什么关联关系没意义了,条件不为真时就全部过滤掉。

第四步:

group by 子句将中的唯一的值组合成为一组,得到虚拟表vt5。如果使用了group by,那么后面的所有步骤都只能得到的vt5的列或者是聚合函数(count、sum、avg等)。原因在于最终的结果集中只为每个组包含一行。这一点请牢记。 应用cube或者rollup选项,为vt5生成超组,生成vt6.

第五步:

使用having筛选器生成vt7。having筛选器是第一个也是为唯一一个应用到已分组数据的筛选器。 处理select子句。将vt7中的在select中出现的列筛选出来。生成vt8. 应用distinct子句,vt8中移除相同的行,生成vt9。事实上如果应用了group by子句那么distinct是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所以的记录都将是不相同的。

第六步:

应用order by子句。按照order_by_condition排序vt9,此时返回的一个游标,而不是虚拟表。sql是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。对表进行排序的查询可以返回一个对象,这个对象包含特定的物理顺序的逻辑组织。这个对象就叫游标。正因为返回值是游标,那么使用order by 子句查询不能应用于表表达式。排序是很需要成本的,除非你必须要排序,否则最好不要指定order by,最后,在这一步中是第一个也是唯一一个可以使用select列表中别名的步骤。 应用top选项。此时才返回结果给请求者即用户。

例如:有如下表执行一个运行过程

select 考生姓名, max(总成绩) as max总成绩

from tb_Grade

where 考生姓名 is not null

group by 考生姓名

having max(总成绩) > 600

order by max总成绩

在上面的示例中 SQL 语句的执行顺序如下:    (1). 首先执行 FROM 子句, 从 tb_Grade 表组装数据源的数据    (2). 执行 WHERE 子句, 筛选 tb_Grade 表中所有数据不为 NULL 的数据    (3). 执行 GROUP BY 子句, 把 tb_Grade 表按 "学生姓名" 列进行分组(注:这一步开始才可以使用select中的别名,他返回的是一个游标,而不是一个表,所以在where中不可以使用select中的别名,而having却可以使用,感谢网友 zyt1369 提出这个问题)   (4). 计算 max() 聚集函数, 按 "总成绩" 求出总成绩中最大的一些数值    (5). 执行 HAVING 子句, 筛选课程的总成绩大于 600 分的.    (7). 执行 ORDER BY 子句, 把最后的结果按 "Max 成绩" 进行排序.

总结:

sql语句执行的顺序:开始 FROM子句--->WHERE子句---->GROUP BY子句---->HAVING子句---->ORDER BY子句---->SELECT子句---->LIMIT子句---->最终结果

每个子句执行后都会产生一个中间结果,供接下来的子句使用,如果不存在某个子句,就跳过对比了一下,mysql和sql执行顺序基本是一样的

未完待续......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值