MySql系列五:SQL语句 的执行顺序

目录

1.FROM 子句连接

 2.ON 子句过滤

3.JOIN 子句连接

4.WHERE 子句过滤

5.GROUP BY 子句(开始使用select中的别名,后面的语句中都可以使用)

6.cube或者rollup

7.HAVING 子句(很耗资源,尽量少用)

8.SELECT 子句

9.DISTINCT 子句

10.ORDER BY 子句

11.LIMIT 子句


有一次面试被问到:你知道SQL语句的执行顺序吗?

瞬间懵逼,平时写的sql语句倒是不少,但是并没有关心它是按什么顺序执行的。所以只能回家等通知了(我猜面试官肯定心里在想,连这个都不会,还出敢来面试。开个玩笑~)。

今天抽时间整理一下,加深自己的印象,同时希望能够帮助其他小伙伴,废话不多说,直接上一个连表查询的sql语句:

SELECT 
DISTINCT
    < select_list >
FROM
    < left_table > < join_type >
JOIN < right_table > 
ON < join_condition >
WHERE
    < where_condition >
GROUP BY
    < group_by_list >
HAVING
    < having_condition >
ORDER BY
    < order_by_condition >
LIMIT < limit_number >

执行顺序FROM ... WHERE ... GROUP BY ... HAVING ... SELECT .... DISTINCT ... ORDER BY ... LIMIT

1.FROM 子句连接

对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1。

首先先来解释一下什么是笛卡尔积

现在我们有两个集合 A = {0,1} , B = {2,3,4}

那么,集合 A * B 得到的结果就是

A * B = {(0,2)、(1,2)、(0,3)、(1,3)、(0,4)、(1,4)};

B * A = {(2,0)、{2,1}、{3,0}、{3,1}、{4,0}、(4,1)};

上面 A * B 和 B * A 的结果就可以称为两个集合相乘的 笛卡尔积

我们可以得出结论,A 集合和 B 集合相乘,包含了集合 A 中的元素和集合 B 中元素之和,也就是 A 元素的个数 * B 元素的个数。

那什么是虚表呢?

在 MySQL 中,有三种类型的表

一种是永久表,永久表就是创建以后用来长期保存数据的表

一种是临时表,临时表也有两类,一种是和永久表一样,只保存临时数据,但是能够长久存在的;还有一种是临时创建的,SQL 语句执行完成就会删除。

一种是虚表,虚表其实就是视图,数据可能会来自多张表的执行结果。

 2.ON 子句过滤

然后对 FROM 连接的结果进行 ON 筛选,将 ON 中的逻辑表达式将应用到 VT1 中的各个行,筛选出满足ON逻辑表达式的行,生成虚拟表 VT2,把符合记录的条件存在 VT2 中。

3.JOIN 子句连接

如果是outer join(left join、rigth join),那么这一步就将添加外部行,left outer jion 就把左表在第二步中过滤的添加进来,right outer join 那么就将右表在第二步中过滤掉的行添加进来,这样生成虚拟表 VT3。

如果 from 子句中的表数目大于两个表,那么就将VT3和第三个表连接从而计算笛卡尔乘积,生成虚拟表,该过程就是一个重复1-3的步骤,最终得到一个新的虚拟表VT3。 

4.WHERE 子句过滤

 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中。

WHERE 和 ON 的区别

  • 如果有外部列,ON 针对过滤的是关联表,主表(保留表)会返回所有的列;
  • 如果没有添加外部列,两者的效果是一样的;

应用

  • 对主表的过滤应该使用 WHERE;
  • 对于关联表,先条件查询后连接则用 ON,先连接后条件查询则用 WHERE;

5.GROUP BY 子句(开始使用select中的别名,后面的语句中都可以使用)

group by 子句将中的唯一的值组合成为一组,产生虚拟机表 VT5。如果应用了group by,那么后面的所有步骤都只能得到的 VT5 的列或者是聚合函数(count、sum、avg等)。原因在于最终的结果集中只为每个组包含一行。

6.cube或者rollup

应用cube或者rollup选项,为VT5生成超组,生成VT6。 

7.HAVING 子句(很耗资源,尽量少用)

 应用having筛选器,把符合条件的放在VT7。having筛选器是第一个也是为唯一一个应用到已分组数据的筛选器。 

避免使用HAVING 子句,HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序、总计等操作。

如果能通过Where 子句在GROUP BY前限制记录的数目,那就能减少这方面的开销。

8.SELECT 子句

执行select操作,在VT7中筛选出select指定的列,插入到虚拟表VT8中。

少用*号,尽量取字段名称

9.DISTINCT 子句

应用distinct子句,在VT8中移除相同的行,生成 VT9。

事实上如果应用了group by子句那么distinct是多余的,原因在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所有的记录都将是不相同的。

10.ORDER BY 子句

应用 order by 子句。按照 order_by_condition 排序 VT9,此时返回的一个游标,而不是虚拟表。sql 是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。

对表进行排序的查询可以返回一个对象,这个对象包含特定的物理顺序的逻辑组织。这个对象就叫游标。正因为返回值是游标,那么使用order by 子句查询不能应用于表表达式。排序是很需要成本的,除非你必须要排序,否则最好不要指定order by。在这一步中是第一个也是唯一一个可以使用select列表中别名的步骤。 

11.LIMIT 子句

limit 子句从上一步得到的结果中选出从指定位置开始的指定行数据,常用来做分页。

 

参考:

https://blog.csdn.net/qq_36894974/article/details/105594307

https://www.cnblogs.com/yyjie/p/7788428.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值