SQL 的执行顺序
了解 SQL 的执行顺序非常有价值,它可以让我们写出语法正确的 SQL,帮助我们简化编写新查询的过程。
本文将在 MySQL 的基础上,介绍查询语句的执行顺序。下面是我们经常看到的查询语句的语法结构:
SELECT <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_list>LIMIT <limit_number>
它的执行顺序:
-
FROM
/JOIN
和所有ON
条件 WHERE
GROUP BY
HAVING
SELECT
ORDER BY
LIMIT
以上是 SQL 标准定义的执行顺序。实际上,如果是简单的单表查询,即查询语句里面只包含了一张表,它将严格按照定义的执行顺序执行查询。对于多表查询,数据库有的时候并没有按此顺序运行查询,因为它们实现了一系列优化使查询运行更快。这些优化可能会改变实际的执行顺序,但它们最终必须返回与以默认的执行顺序运行查询的结果相同。
按照执行顺序的规则,排在后面的子句产生的结果不能被前面的子句引用。比如:
- 不能在
WHERE
子句里面使用SELECT
子句设置的别名,因为WHERE
子句先于SELECT
子句执行;
# 执行失败,提示“Unknown column 'ename_job' in 'where clause'”SELECT CONCAT(ename, '|', job) AS ename_job FROM emp WHERE ename_job = 'KING|PRESIDENT'
2. 不能在 WHERE
子句里面过滤 GROUP BY
子句的聚合结果,因为 WHERE
子句先于 GROUP BY
子句执行;
# 执行不通过,提示“Invalid use of group function”SELECT deptno, COUNT(*) AS cnt FROM emp WHERE COUNT(*) > 0GROUP BY deptno
3. 可以在 ORDER BY
子句中引用 GROUP BY
子句聚合的结果,因为 ORDER BY
子句的执行顺序在 GROUP BY
子句之后。
# 执行成功SELECT deptno, COUNT(*) FROM emp GROUP BY deptno ORDER BY COUNT(*)
在 MySQL 里面,我们会看到一些“反常”的操作。
比如下面这条 SQL ,看起来像是 SELECT
子句的别名被 GROUP BY
子句引用。
SELECT CONCAT(job, '|', deptno) AS job_dept, COUNT(*) FROM emp GROUP BY job_dept
那是不是说这条 SQL 破坏了前面定义的执行顺序呢?实际上并没有,MYSQL 会对这条 SQL 做重写,像这样:
SELECT CONCAT(job, '|', deptno), COUNT(*) FROM emp GROUP BY CONCAT(job, '|', deptno)
再有,比如下面这条多表关联查询的语句。
SELECT e.*, d.dname FROM emp e LEFT JOIN dept d ON d.deptno = e.deptno WHERE e.job = 'PRESIDENT'
假如 emp 表和 dept 都是很大的表,emp 通过条件 job = 'PRESIDENT'
过滤后会得到很小的结果集。如果按照标准的执行顺序先执行两个大表的 LEFT JOIN
再执行 WHERE
过滤,那整个 JOIN 操作将会占用很大的内存。MySQL 可能会对 emp 表先执行WHERE
子句的过滤操作,过滤后的结果集再和 dept 表关联。
- 企业支付宝账号开发接口教程--JAVA-UTF-8(实际操作------SpringMVC+JSP)
- 用pandas 进行投资分析
- 【专业技术】android 应用程序如何获取root权限
- Nginx+Keepalived(双机热备)搭建高可用负载均衡环境(HA)
- SpringMVC+MongoDB+Maven整合(微信回调Oauth授权)
- ZeroClipboard实现多个浏览器兼容的复制文本到剪贴板的功能
- Shiro 权限框架使用总结
- Apriori算法介绍(Python实现)
- linux学习第六十二篇:添加自定义监控项目,配置邮件告警,测试告警,不发邮件的问题处理
- Entity Framework Core 2.0 入门
- Nodejs开发框架Express3.0开发手记–从零开始
- 使用 nvm 管理不同版本的 node 与 npm
- svg矢量图绘制以及转换为Android可用的VectorDrawable资源
- CListCtrl控件使用方法总结
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- GlassFish 目录穿越漏洞测试过程
- 安装CDH7.1.1
- GIT-SHELL 沙盒绕过(CVE-2017-8386)
- Azkaban-2.5.0-部署与常见案例
- 无字母数字webshell之提高篇
- Sqoop-1.4.7-部署与常见案例
- Hbase-2.0.0_01_安装部署
- 前端黑魔法之远程控制地址栏
- 攻击LNMP架构Web应用的几个小Tricks
- Hbase-2.0.0_02_常用操作
- phpjiami 数种解密方法
- Hbase-2.0.0_03_Hbase数据模型
- ELK-elasticsearch-6.3.2部署
- Real World CTF 2018 bookhub 总结
- python http.server open redirect vulnerability