sql语句执行顺序

1.sql的执行数据

顺序如下:

  • 1.from
  • 2.on
  • 3.join
  • 4.where
  • 5.group by
  • 6.sum、avg…
  • 7.having
  • 8.select
  • 9.distinct
  • 10.order by

2.SQL查询语句的执行顺序示例:

(7)     SELECT 
(8)     DISTINCT <select_list>
(1)     FROM <left_table>
(3)     <join_type> JOIN <right_table>
(2)     ON <join_condition>
(4)     WHERE <where_condition>
(5)     GROUP BY <group_by_list>
(6)     HAVING <having_condition>
(9)     ORDER BY <order_by_condition>
(10)    LIMIT <limit_number>

查询语句的真正逻辑顺序,如上图所示每一行前面的排序所示,第一步实际上不是SELECT,而是FROM。

(1)from:笛卡尔积

第一步其实是先执行的FROM语句,先查询左表还是右表呢,都不是,直接先做笛卡儿积,这个笛卡尔积的结果集,暂时为VT
1

(2)on:过滤

执行完笛卡尔积后,会对其结果根据on中指定的条件进行过滤,去掉那些不符合条件的数据,此时得到虚拟表VT2

(3)join:添加外部行

此步骤只有连接类型为外连接时才会执行,即out join,例如left outer join,right outer join和full outer join,这时候我们会省略关键字outer,但是你要知道注入的left join属于外连接(inner join以及 , 都属于内连接)

因为右连接实际上可以通过左连接颠倒表顺序来获取相同结果,所以我们单独以左连接作为说明,我们知道左连接就是以左表为基准,不论是否满足条件,都会在最终结果中留下来,除自身表值,其连接表的列部分赋值为null,而我们上一步也说了,会执行on条件过滤,去掉不符合条件的数据,也就是说那些null值也被过滤了

所以这一步,如果是left join,就是把左表在第二步(on)中被过滤的部分,重新添加到VT2中,形成VT3,如果from子句中还有表需要连接,那么会将VT3作为输入,重复执行步骤1-3,最终得到新的虚拟表VT3

例:

select *
from table1 t1
left join table2 t2 on t1.id = t2.id
left join table3 t3 on t2.id = t3.id
  • 先将t1表和t2表做笛卡尔积(vt1表),然后执行on条件进行过滤(vt2),因为是left join,所以左表被过滤的部分重新添加到vt2中,形成vt3
  • 之后将vt3(vt3表中有t2.id这个值)和t3表做笛卡尔积(vt1表),然后执行on条件过滤…(循环这个步骤)
(4)where:过滤

根据where条件对vt3进行过滤,把符合条件的记录输出到虚拟表vt4中,注意此处还没有执行group by,所以过滤条件中无法使用类似聚合函数等分类统计

(5)group by:分组

group by用于对where条件过滤之后的结果进行分组操作,得到vt5
在这一步中,尽管你可以执行一些分组后内容的聚合函数,但是实际上新的结果集vt5中,只会为每一个组包含一行

(6)having:过滤

having过滤是配合group by使用,对分组后的vt5虚拟表进行条件过滤,得到虚拟表vt6

(7)select:列表

虽然select写在第一行,但是并非第一个执行的,此时select才从虚拟表vt6中提取我们选择的列,形成新的虚拟表vt7

(8)distinct:去重

如果在查询中指定了DISTINCT子句,则会创建一张内存临时表(如果内存放不下,就需要存放在硬盘了)。这张临时表的表结构和上一步产生的虚拟表VT7是一样的,不同的是对进行DISTINCT操作的列增加了一个唯一索引,以此来除重复数据。

(9)order by:排序

对虚拟表中的内容,按照指定的列进行排序,饭后返回一个新的虚拟表VT8。

(10)limit:限制

最终,走到最后一步了,对VT8虚拟表从指定位置开始抓取指定条数的数据,把最终的结果返回。


3.浅谈一个坑

直接用例子来说明,假如有两张表如下,学生表(班级,姓名)和成绩表(姓名,成绩),现在我们需要返回A班级中全体学生的成绩,但是这个班中有学生缺考,缺考的学生我们也不能漏,所以这里我们用学生表作为左表,进行左连接
在这里插入图片描述
我们尝试使用以下的SQL来执行(为了方便对比,这里把两张表的列都输出了):
在这里插入图片描述
乍一看似乎没什么问题,又是左连接又在ON条件中增加了班级限制,实际上的结果却出现了B班的同学,为什么?
在这里插入图片描述
正是因为SQL执行顺序的问题,在步骤1-3中我们说过,外连接时也是要先做笛卡儿积,根据ON条件筛选后,注意,然后会再将保留表中被过滤的行重新添加回来。

所以实际上这个结果是这样组成的:ON条件过滤后的记录 + 保留表中被过滤的记录
在这里插入图片描述
所以,为了准确得到我们希望的结果,最终班级的过滤应该放在后面执行的WHERE中去:
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值