MySQL中明确查询语句的执行顺序极其重要,了解执行顺序才不至于犯一些简单错误,例如having 后面是否可以使用 select 中重命名的列名等问题。另外SQL中实际使用最频繁的就是查询(Queing),要想写出高质量、高性能的查询语句,必须深入地了解SQL的逻辑查询处理顺序和机制。
一、查询语句的执行顺序
基础查询语句
(5) select distinct top(<取数说明>) <选择 列表> (1) from <表1> <连接类型> join <表2> ON <连接条件> (2) where <筛选条件> (3) group by <分组条件> (4) having <条件> (6) order by <排序的列、排序规则> (7) limit <选择行>
注意
1、select:避免使用 select * 。按照需要进行数据查询,否则会导致查询速度变慢。避免查询多余数据。
2、where:因为还没有对数据进行分组,所以where 不能和聚合函数(count、sum、max等函数)一起使用,也不能引用 select 列表中创建的别名,因为 select 还没有执行。
3、group by 和 having:在 group by 和 having 中不可以直接使用select中重命名的列。
4、order by:但是在 order by 中可以直接使用select中重命名的列。
5、limit:如果只需要查询出一条数据,使用 limit 1。例如,想要知道是否有男生,只要能查询到一条含有男生的记录就可以。使用Limit 1 可以在找到一条数据后停止搜索,避免多余查询。
SQL并没有按照编写语句的顺序曲执行语句。上边的序号,就是查询语句在执行过程中处理逻辑的顺序。
二、查询处理机制
每个执行过程主要做那些事呢,下面具体介绍:
(1)FROM
该过程从数据库中选取需要查询的表或视图。并处理表运算符。
在涉及到联接运算的查询中(各种join),主要有以下几个步骤:
- 求笛卡尔积。不论是什么类型的联接运算,首先都是执行交叉连接(cross join),求笛卡儿积,生成虚拟表VT1-J1。
- ON 筛选器。这个阶段对上个步骤生成的 VT1-J1 进行筛选,根据ON中出现的谓词进行筛选,让谓词取值为 true的行插入到VT1-J2。
- 添加外部行。如果指定了 outer join,还需要将VT1-J2 中没有找到匹配的行,作为外部行添加到VT1-J2中,生成VT1-J3。
经过以上步骤,FROM 执行过程就完成了。
概括地讲,FROM 执行过程就是找到表并进行数据的预处理,根据条件对表进行处理。
(2)WHERE
从表或视图中筛选出满足条件的行。根据<筛选条件>中条件对 VT1中的行进行筛选,让满足条件的行插入到 VT2中。
(3)GROUP BY
根据指定的列对筛选出的行进行分组。按照指定的列名,将 VT2中的进行分组,生成VT3。最后每个分组只有一行。
(4)HAVING
从分组后的数据中筛选出满足条件的行。根据 having子句中出现的谓词对VT3的分组进行筛选,并将符合条件的组插入到 VT4中。
(5)SELECT
从表或视图中选取需要的列。这个阶段是投影的过程,处理select子句中提到的列,产生VT5。
一般按下列顺序进行:
- 计算 select 列表中的表达式,生成VT5-1。
- 若有 distinct,则删除VT5-1中的重复行,生成VT5-2。
- 若有 top,则根据 order by 子句定义的逻辑顺序,从VT5-2 中选择签名指定数量或者百分比的行,生成VT5-3。
(6)ORDER BY
根据指定的列对筛选出的行进行排序。按照 order by 子句中指定的列名,对VT5中的行,进行排序,生成游标VC6。
(7)LIMIT
根据指定的条件对筛选出的行再次进行筛选。按照 limit 子句中指定的行的位置,对Vc6中的行进行选择,生成VT7。