小伙伴想精准查找本身想看的MySQL文章?喏 → MySQL专栏目录 | 点击这里sql
SQL 查询的执行顺序是怎样的?数据库
好像这个问题应该很好回答,毕竟本身已经写了无数个 SQL 查询了,有一些还很复杂的。还装不了这个逼了?!函数
但事实是,我仍然很难确切地说出它的顺序是怎样的。学习
言归正传,SELECT语句的完整语法以下:优化
1. SELECT 2. DISTINCT <select_list> 3. FROM <left_table> 4. <join_type> JOIN <right_table> 5. ON <join_condition> 6. WHERE <where_condition> 7. GROUP BY <group_by_list> 8. HAVING <having_condition> 9. ORDER BY <order_by_condition> 10.LIMIT <limit_number>
然而其执行顺序倒是:url
FROM
<表名> # 笛卡尔积
ON
<筛选条件> # 对笛卡尔积的虚表进行筛选
JOIN <join, left join, right join...>
<join表> # 指定join,用于添加数据到on以后的虚表中,例如left join会将左表的剩余数据添加到虚表中
WHERE
<where条件> # 对上述虚表进行筛选
GROUP BY
<分组条件> # 分组
<SUM()等聚合函数> # 用于having子句进行判断,在书写上这类聚合函数是写在having判断里面的
HAVING
<分组筛选> # 对分组后的结果进行聚合筛选
SELECT
<返回数据列表> # 返回的单列必须在group by子句中,聚合函数除外
DISTINCT
# 数据除重
ORDER BY
<排序条件> # 排序
LIMIT
<行数限制>spa
- 其实,引擎在执行上述每一步时,都会在内存中造成一张虚拟表,而后对虚拟表进行后续操做,并释放没用的虚拟表的内存,以此类推。
具体解释:(注:下面“VT”表示 → 虚拟表 virtual ).net
- from:select * from table_1, table_2; 与 select * from table_1 join table_2; 的结果一致,都是表示求笛卡尔积;用于直接计算两个表笛卡尔积,获得虚拟表VT1,这是全部select语句最早执行的操做,其余操做时在这个表上进行的,也就是from操做所完成的内容
- on: 从VT1表中筛选符合条件的数据,造成VT2表;
- join: 将该 join 类型的数据补充到VT2表中,例如 left join 会将左表的剩余数据添加到虚表VT2中,造成VT3表;若表的数量大于2,则会重复1-3步;
- where: 执行筛选,(不能使用聚合函数)获得VT4表;
- group by: 对VT4表进行分组,获得VT5表;其后处理的语句,如select,having,所用到的列必须包含在group by条件中,没有出现的须要用聚合函数;
- having: 筛选分组后的数据,获得VT6表;
- select: 返回列获得VT7表;
- distinct: 用于去重获得VT8表;
- order by: 用于排序获得VT9表;
- limit: 返回须要的行数,获得VT10;
须要注意的是:code
- group by条件中,每一个列必须是有效列,不能是聚合函数;
- null值也会做为一个分组返回;
- 除了聚合函数,select子句中的列必须在group by条件中;
上述内容让咱们知道一个查询会返回什么,同时,也回答了如下这些问题:blog
- 能够在 GRROUP BY 以后使用 WHERE 吗?(不行,GROUP BY 是在 WHERE 以后!)
- 能够对窗口函数返回的结果进行过滤吗?(不行,窗口函数是 SELECT 语句里,而 SELECT 是在 WHERE 和 GROUP BY 以后)
- 能够基于 GROUP BY 里的东西进行 ORDER BY 吗?(能够,ORDER BY 基本上是在最后执行的,因此能够基于任何东西进行 ORDER BY)
- LIMIT 是在何时执行?(在最后!)
可是,数据库引擎并不必定严格按照这个顺序执行 SQL 查询,由于为了更快地执行查询,它们会作出一些优化,这些问题会在下方进行解释↓↓↓。
SQL中的别名会影响SQL执行顺序么?
以下方SQL所示:
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*) FROM table GROUP BY full_name
从这个语句来看,好像 GROUP BY 是在 SELECT 以后执行的,由于它引用了 SELECT 中的一个别名。但实际上不必定要这样,数据库引擎会把查询重写成这样↓↓↓:
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*) FROM table GROUP BY CONCAT(first_name, ' ', last_name)
因此,这样 GROUP BY 仍然先执行。
另外,数据库引擎还会作一系列检查,确保 SELECT 和 GROUP BY 中的东西是有效的,因此会在生成执行计划以前对查询作一次总体检查。
数据库极可能不按正常顺序执行查询(优化)
在实际当中,数据库不必定会按照 JOIN、WHERE、GROUP BY 的顺序来执行查询,由于它们会进行一系列优化,把执行顺序打乱,从而让查询执行得更快,只要不改变查询结果。
这个查询说明了为何须要以不一样的顺序执行查询:
SELECT * FROM dept d LEFT JOIN student s ON d.student_id = s.id WHERE s.name = '陈哈哈'
若是只须要找出名字叫“陈哈哈”的学生信息,那就不必对两张表的全部数据执行左链接,在链接以前先进行过滤,这样查询会快得多,并且对于这个查询来讲,先执行过滤并不会改变查询结果。
能看到这里的朋友都是有缘人了,为你的学习力点赞!但愿大佬也能为小弟点赞支持一下哦!
本文同步分享在 博客“_陈哈哈”(CSDN)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。