SQL 的执行顺序

时间:2022-07-22
本文章向大家介绍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>

它的执行顺序:

  1. FROM / JOIN 和所有 ON 条件
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY
  7. LIMIT

以上是 SQL 标准定义的执行顺序。实际上,如果是简单的单表查询,即查询语句里面只包含了一张表,它将严格按照定义的执行顺序执行查询。对于多表查询,数据库有的时候并没有按此顺序运行查询,因为它们实现了一系列优化使查询运行更快。这些优化可能会改变实际的执行顺序,但它们最终必须返回与以默认的执行顺序运行查询的结果相同。

按照执行顺序的规则,排在后面的子句产生的结果不能被前面的子句引用。比如:

  1. 不能在 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 表关联。