MYSQL 语句执行顺序

用一条复杂的语句记录顺序:

1
2
3
4
5
6
7
8
9
10
(7)     SELECT
(8) DISTINCT <select_list>
(1) FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) HAVING <having_condition>
(9) ORDER BY <order_by_condition>
(10) LIMIT <limit_number>

解析:

  1. FROM: 对 FROM 的左边的表和右边的表计算笛卡尔积。产生虚表 VT1
  2. ON: 对虚表 VT1 进行 ON 筛选,只有那些符合 <join-condition> 的行才会被记录在虚表VT2中。
  3. JOIN: 如果指定了 OUTER JOIN(比如 left join、right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表 VT2 中,产生虚拟表 VT3, rug from 子句中包含两个以上的表的话,那么就会对上一个 join 连接产生的结果 VT3 和下一个表重复执行步骤 1~3 这三个步骤,一直到处理完所有的表为止。
  4. WHERE: 对虚拟表 VT3 进行 WHERE 条件过滤。只有符合 <where-condition> 的记录才会被插入到虚拟表 VT4 中。
  5. GROUP BY: 根据 group by 子句中的列,对 VT4 中的记录进行分组操作,产生 VT5.
  6. CUBE | ROLLUP: 对表 VT5 进行 cube 或者 rollup 操作,产生表 VT6.
  7. HAVING: 对虚拟表 VT6 应用 having 过滤,只有符合 <having-condition> 的记录才会被插入到虚拟表 VT7 中。
  8. SELECT: 执行 select 操作,选择指定的列,插入到虚拟表 VT8中。
  9. DISTINCT: 对 VT8 中的记录进行去重。产生虚拟表 VT9.
  10. ORDER BY: 将虚拟表 VT9 中的记录按照 <order_by_list> 进行排序操作,产生虚拟表 VT10.
  11. LIMIT:取出指定行的记录,产生虚拟表 VT11, 并将结果返回。

另外需要注意的问题:

(1) GROUP BY 存在时,SELECT 中除了聚集函数外,所有的基本列必须是 GROUP BY 里面存在的。参见 《SQL_MODE = ONLY_FULL_GROUP_BY》
(2) HAVING 基本上同 GROUP BY 一起使用的,HAVING 类似于 WHERE 语句,只是 HAVING 过滤是基于 GROUP BY 分组后的数据,HAVING 一般通过 SELECT 语句里面的聚集函数进行过滤。

参考文章:https://www.cnblogs.com/rollenholt/p/3776923.html