灵魂拷问,SQL 查询语句先执行 SELECT吗?
大家平时和SQL语句打交道的时间肯定不少,有写过简单SQL的,也有为很复杂的业务逻辑的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>
然而其执行顺序却是下面这样的
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
<行数限制>
其实,sql引擎在执行上述每一步时,都会在内存中形成一张虚拟表,然后对虚拟表进行后续操作,并释放没用的虚拟表的内存,以此类推。
具体过程如下:(下面“VT”表示 → 虚拟表 virtual )
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;
需要注意的是:
group by条件中,每个列必须是有效列,不能是聚合函数;
null值也会作为一个分组返回;
除了聚合函数,select子句中的列必须在group by条件中;
上述内容让我们知道一个查询会返回什么,同时,也回答了以下这些问题:
可以在 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 = 'AAA'
如果只需要找出名字叫AAA学生信息,那就没必要对两张表的所有数据执行左连接,在连接之前先进行过滤,这样查询会快得多,而且对于这个查询来说,先执行过滤并不会改变查询结果。
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️
灵魂拷问,SQL 查询语句先执行 SELECT吗?相关推荐
- 一条SQL查询语句的执行过程,一张图说清SQL查询语句执行过程
一张图说明 一条SQL查询语句的执行过程 一条sql语句从发送到数据库到它执行完成并返回结果,主要经历以下几个过程: 连接器->查询缓存(如果开启了查询缓存,则会经过这一步,但是大多数情况下都是 ...
- SQL优化之SQL查询语句的执行顺序解析
SQL语句执行顺序 SQL语句执行顺序 结合上图,整理出如下伪SQL查询语句. SQL语句执行顺序 从这个顺序中我们可以发现,所有的查询语句都是从 FROM 开始执行的.在实际执行过程中,每个步骤都会 ...
- SQL 查询总是先执行SELECT语句吗?你们都错了!
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 译者:无明 链接:infoq.cn/article/Oke8hgi ...
- SQL 查询总是先执行SELECT语句吗?你们都错了!
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | infoq.cn/article/Oke8hg ...
- SQL 查询总是先执行SELECT语句吗?
点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取近百本电子书入口 译者:无明 链接:22j.co/b8Un 很多 SQL 查 ...
- 讲mysql执行流程书籍_MySQL 基础架构 1. 一条SQL查询语句的执行过程(个人学习笔记)...
MySQL的逻辑架构图: MySQL 大体分为 "server 层" 和 "存储引擎层" 两部分: Server 层 包括 连接器.查询缓存.分析器.优化器.执 ...
- esp32查询剩余内存_SQL 查询语句先执行 SELECT?兄弟你认真的么?
SQL 查询的执行顺序是怎样呢? 好像这个问题应该很好回答,毕竟自己已经写了无数个 SQL 查询了,有一些还很复杂的. 但事实是,这个问题小编很难确切地说出它的顺序是怎样的. 言归正传,SELECT语 ...
- SQL查询语句逻辑执行顺序
1.查询语句的逻辑执行顺序 执行1:from 执行2:on 执行3:join 执行4:where 执行5:group by 执行6:having 执行7:select 执行8:distinct 执行9 ...
- mysql 中 sql 查询语句的执行过程 (mysql基本架构)
mysql总体上分为server层和存储引擎层 server层负包括连接器.缓存.解析器.优化器.执行器 存储引擎层则负责存储数据 连接器 连接器负责跟客户端建立连接.获取权限.维持和管理连接. 它首 ...
最新文章
- 使用Python+OpenCV+yolov5实现行人目标检测
- 每天一点点之vue框架开发 - axios解决跨越问题
- JVM - 再聊GC垃圾收集算法及垃圾收集器
- 第03课:Anaconda 与 Jupyter Notebook
- 八代i7装服务器系统2012,八代I7能装win7系统吗,会影响性能吗-8代win7,8代cpu完美装win7...
- 牛客练习赛19 E和F(签到就走系列)托米的饮料+托米搭积木
- 日志分割工具cronolog
- 二叉树的存储结构及四种遍历(C语言)
- c# mysql 操作_c#对mysql数据库的基本操作
- 数据新动能:帆软第四届智数大会圆满落幕
- bzoj3129 [Sdoi2013]方程 容斥+扩展lucas
- SQL语句和EF Group by 用法
- 卷积的感受野计算及特征图尺寸计算
- SPFA算法判断负环
- jQuery 下载与安装教程
- 树形控件之思维导图 Android
- net-java-php-python-社会福利保障系统计算机毕业设计程序
- 微信小程序在线考试系统 毕业设计(2)分类
- cypress初识--看完就可以写一个简单web自动化脚本了!
- 【边缘计算】刘阳:边缘计算发展中的若干热点问题及思考
热门文章
- java无ide编译_[转]无IDE时编译和运行Java
- php mysql mvc_超简洁PHPMVC
- Android横向滚动卡片,Android实现横向滑动卡片效果
- python如何画虚线_Python威力巨大,五分钟如何绘制出漂亮的系统架构图?
- linkbot 中文教程系列 linkbot破解教程
- 如果你需要在 XHTML 中声明 DOCTYPE,必须使用到jsp:text动作元素
- 字符串经典题之扑克牌的大小
- (王道408考研数据结构)第八章排序-第一节:排序综述
- qt widget 窗口句柄的问题
- windows Tracert命令