目录
前言
今天同事问了我个问题,select语句中的别名可以在哪些地方使用,一听这个我就想到了聚合函数、group by、having、order by 。然后它又问我可以在 join on中使用嘛?,我陷入了思考,想了下这其实跟select语句的执行顺序有关,因为记不太清了,所以再次学习了下,并记录一下。
试验环境
Mysql 5.7
一、语句结构
SELECT DISTINCT ...,...,...
FROM ...
JOIN ... ON ... 多表的连接条件
JOIN ... ON ...
WHERE ... AND/OR... 不包含组函数的过滤条件
GROUP BY ...,...
HAVING ... 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...
二、执行步骤
在MySQL中,SELECT语句的执行顺序可以分为以下几个步骤:
-
FROM子句:首先,MySQL会从FROM子句中指定的表中检索数据。如果FROM子句中包含多个表,MySQL会根据连接条件将它们连接起来。
-
ON子句:接下来,MySQL会根据ON子句中的条件过滤出符合条件的数据。
-
WHERE子句:然后,MySQL会根据WHERE子句中的条件过滤出符合条件的数据。只有符合WHERE条件的数据才会被查询出来。
-
GROUP BY子句:如果查询语句中有GROUP BY子句,MySQL会根据GROUP BY子句中指定的列对查询结果进行分组。每个分组都会有一个唯一的组标识。
-
聚合函数
-
HAVING子句:如果查询语句中有HAVING子句,MySQL会根据HAVING子句中的条件过滤出符合条件的分组。只有符合HAVING条件的分组才会被查询出来。
-
SELECT子句:接下来,MySQL会根据SELECT子句中指定的列从查询结果中提取出需要的数据。
-
DISTINCT关键字:如果查询语句中包含DISTINCT关键字,MySQL会去除查询结果中的重复行。
-
ORDER BY子句:如果查询语句中有ORDER BY子句,MySQL会根据ORDER BY子句中指定的列对查询结果进行排序。
-
LIMIT子句:最后,如果查询语句中有LIMIT子句,MySQL会根据LIMIT子句指定的数量限制查询结果的行数。
总体来说,SELECT语句的执行顺序是按照以上步骤逐步执行的。根据查询语句中的不同子句,MySQL会在执行过程中进行不同的操作,最终返回符合条件的查询结果。
三、查询过程
- 首先根据FROM后边的前两个表做一个笛卡尔积生成虚拟表table1,对应步骤1
笛卡尔积 笛卡尔积是集合论中的一个概念,表示两个集合的所有可能的有序对组成的集合。 假设A和B是两个集合,A={a, b},B={1, 2}。那么A和B的笛卡尔积可以表示为A×B ={(a, 1), (a, 2), (b, 1), (b, 2)}。 简单来说,笛卡尔积就是将两个集合的每个元素进行组合,得到所有可能的有序对。 结果集合中的每个元素都由一个A中的元素和一个B中的元素组成,且顺序不同则为 不同的元素。
- 然后根据ON语句的条件对table1进行筛选生成table2,对应步骤2
- 然后根据连接关键字Left、Right、Outer等,对table2进行补充形成table3
具体过程 Left 左表为基础表,右表对应数据不存在则为Null,形成新的虚拟表 RIGHT 右表为基础表,左表对应数据不存在则为Null,形成新的虚拟表
- 如果超过两张表就重复1-3最终形成虚拟表table4
- 通过where语句进行筛选,形成虚拟表table5,对应步骤3
- 有group by 语句,就对table5分组形成 虚拟表table6,对应步骤4
- 应用cube或者rollup选项,生成超组,对分组后结果执行聚合函数形成虚拟表table7,对应步骤5
cube、rollup选项是什么? CUBE和ROLLUP都是用于生成多维聚合报表的选项。 CUBE选项允许在GROUP BY子句中同时生成多个聚合级别的汇总数据。它会生成所有可能的组合, 包括空值。例如,如果有两个维度A和B,那么CUBE(A, B)将生成包括(A,B),(A,NULL), (NULL,B)和(NULL,NULL)的所有组合。 ROLLUP选项类似于CUBE,但是它只生成按照指定顺序的聚合级别。ROLLUP(A, B)将生成(A,B) ,(A,NULL)和(NULL,NULL)这三个级别的组合。
- 执行having 语句,对分组进行筛选形成虚拟表table8,对应步骤6
- 应用select语句,保留相应的列,生成虚拟表table9,对应步骤7
- 有DISTINCT语句,移除重复行,生成虚拟表table10,对应步骤8
- 执行order by子句,此时返回的一个游标,对应步骤9
什么是游标? MySQL游标是一个用于在数据集上进行迭代的数据库对象。它类似于在编程中使用的游标概念, 可以将游标看作是一个指针,可以依次访问数据集中的每一行。
- Limit筛选返回的数据条数,对应步骤10
四、疑问
分析完mysql的执行顺序,很明显别名不可以在join on中使用,因为join on在select之前就执行了,但是我又产生了新的疑问:
- select在group by之后执行,为什么group by中可以使用别名?
- 用on筛选和用where筛选有什么区别?
- order by在select之后,为什么order by可以用select中未选择的列呢?
问题1:select在group by之后执行,为什么group by中可以使用别名?
mysql官网也没有给出具体原因
但目前可以确定的是:select肯定在group by之前执行了一次,可以理解成在原有顺序的基础上的预加载,也就是说对于mysql,每一次运行代码,实际上执行了至少两次select。
问题2:用on筛选和用where筛选有什么区别?
on和where的最大区别在于,如果在on应用逻辑表达式那么在第三步join中还可以把移除的行再次添加回来,而where的移除的最终的;
问题3:order by在select之后,为什么order by可以用select中未选择的列呢?
没找到答案,希望大佬可以解惑。
总结
本文总结了mysql中select的执行顺序,并对几个常见的疑问进行了解答,希望能对你有所帮助。