数据库SQL查询语句的执行顺序是怎么样的?

目录

1. 引言

2. SQL查询语句举例

3. SQL查询语句顺序执行误区

4. 查询语句步骤分析

5. SQL查询语句执行顺序总结

6. 面试小问题

6.1 WHERE 和 HAVING 谁的过滤范围更广?

6.2 为什么 WHERE 之后不能使用聚合函数进行过滤?

6.3 为什么 WHERE 的执行效率要比 HAVING 高?

6.4 SQL的执行顺序为什么要这样设计呢?


1. 引言

我们都知道,掌握MySql数据库几乎是我们程序员比本的一项基本技能,对于简单的数据库操作而言吗,我们通常做的就是CRUD,无非再加上一些筛选过滤条件,在MySql数据库中,我们会用到很多的关键字,那么个不知道它们的执行顺序是怎么样的呢?

SQL查询语句的执行过程也是很多面试官会问到的一个问题,因此我们必须学会它,理解它。

2. SQL查询语句举例

下面我写一个比较复杂的SQL查询语句,几乎包含了所有的查询关键字以及聚合函数,我们来分析一下它的执行顺序。

SELECT (查询想要获取的字段数据,还可以 DISTINCT 去重)

FROM  (从哪些表中查,写表名,并可以为其起别名)

(LEFT / RIGHT 可有可无) JOIN  (继续跟表名,也可以起别名)

ON  (多表连接的条件,第一次过滤)

WHERE  (不包含聚合函数的过滤条件,BETWEEN...AND... ,IN可以用在WHERE中,第二次过滤)

GROUP BY  (分组关键字,例如通过部门分组)

HAVING  (包含聚合函数的过滤条件,如MAX(),MIN(),AVG()等聚合函数第三次过滤)

ORDER BY  ASC/DESC  (排序关键字,升序或者降序)

LIMIT  X,Y  (分页关键字,X表示从第几条开始,Y表示一页显示多少条)

3. SQL查询语句顺序执行误区

也许有很多人在一开始认为SQL的查询语句都是从上往下执行的,但其实是错的,SQL查询语句的执行顺序并不是按顺序执行的。

MySql在查找数据时会根据一个合适的执行顺序去执行我们的查询语句,从而提高查找数据的效率和操作数据的效率,这也与我们以后要接触的SQL语句的优化有一定的关联性。

4. 查询语句步骤分析

OK,经过上面的层层铺垫,我们开始进入正题,现在我们一步步分析上面的一大长串SQL查询语句的执行顺序,我会尽可能说的详细一些

下面我们就以两张表的查询为例,三张表四张表类比推理即可

(1)第一步,执行 FROM

既然是查询,它就会先去执行 FROM,因为它要知道你要去查询那些表的数据,所以首先会去 FROM,如果只有一张表,底层不会做什么事,如果你有两张以上的表,底层其实会去对这些表中的每一个元素做一个笛卡尔积,其实这个过程中是有一个虚拟表的,这张表的数据量非常大,只是我们不知道;

(2)第二步,执行 ON

在进行完表数据的笛卡尔积之后,紧接着会去执行两张表的连接条件 ON,通过ON的过滤条件,会筛选出来有用的数据,将大量无用数据全部剔除,然后筛选出来的数据又形成了一个新的虚拟表,这张新的虚拟表数据量已经比较小了;

(3)第三步,执行 (RIGHT/LEFT) JOIN

如果我们对两张表进行了左外或者右外连接,在完成第二步筛选之后,就会根据你写的左外LEFT JOIN或者右外 RIGHT JOIN,再去补充一些 ON 连接查询条件中没有查询到的数据,然后对补充后的数据又形成一个新的虚拟表,如果没有左右外连接,那么它就会直接连接,合并数据,形成虚拟表;

(4)第四步,执行WHERE

我们就会去执行 WHERE 中的过滤条件,比如我们IN关键字,BETWEEN...AND...关键字,再次将满足我们条件的数据过滤出来,将无用的数据再次剔除,又形成一张数据量更小虚拟的表;

(5)第五步,执行GROUP BY

我们就会对剩下的少量数据进行分组,执行 GROUP BY分组命令;

(6)第六步,执行 HAVING

完成分组之后,我们还会对数据进行进一步过滤,比如说我们想得到平均工资最高,或者最低的部门相关数据,将通过 HAVING 关键字即可过滤得到,此时,经过了层层过滤,底层的那张虚拟表的数据已经非常非常小了;

(7)第七步,执行 SELECT 。

经过前面六部层层过滤之后,我们得到了一个满足了我们所有条件的一个虚拟表,这个时候我们才会去做 SELECT 操作,因为我们不一定要想要所有数据,可能只要其中的几个字段,此时会再进行 SELECT 操作,将我们想要得字段和相关数据筛选出来。

(8)第八步,执行 DISTINCT。

经过 SELECT 查询之后,我们可能还会对一些重复出现的字段进行去重,此时就会执行 DISTINCT。

(9)第九步,执行ORDER BY (ASC/DESC) 。

DISTINCT 过滤玩字段之后,可以说现在得到的数据就是我们想要的全部数据了,但此时表中的数据还处于一个无序的状态,此时我们可能还想对得到的数据在做一个排序,比如升序排列,降序排列等等。

(10)第十步,执行 LIMIT (X,Y) 。

经过排序之后,我们现在得到的就是已经排好序的而且是含有所有有效数据的一张虚拟表,这个时候我们还会做最后的一步操作,分页,所以说分也页是最后进行的。

5. SQL查询语句执行顺序总结

通过上面我们一大堆的分析,我们可以得出以下结论,在SQL查询语句中,各个关键字以及过滤条件的执行顺序如下

FROM ---> ON ---> (LEFT/RIGHT) JOIN ---> WHERE (BETWEEN...AND.../IN) ---> GROUP BY ---> HAVING ---> SELECT ---> DISTINCT ---> ORDER BY (ASC/DESC) ---> LIMIT 

如下图所示

数据库SQL查询语句的执行顺序是怎么样的?_第1张图片

6. 面试小问题

下面是扩展小问题,这些问题面试的过程中很有可能会问到的哦!希望各位同学认真看完,能真正的理解它们。

6.1 WHERE 和 HAVING 谁的过滤范围更广?

这个问题其实不难,我们知道,HAVING 可以使用聚合函数进行条件过滤,而 WHERE 却不行,因此在过滤范围方面,HAVING 的过滤范围要比 WHERE 的更广泛。

6.2 为什么 WHERE 之后不能使用聚合函数进行过滤?

首先一点我们要知道,想要使用分组函数,首先你得先分好组。通过上面我们的分析可以知道分组操作是在 WHERE 操作执行完之后才会去执行的,那么自然而然,这个问题不就迎刃而解了吗,在进行 WHERE 操作的时候,我们还没有对数据进行分组操作,当然也无法使用分组函数了啊。

6.3 为什么 WHERE 的执行效率要比 HAVING 高?

想要弄明白这个问题,还需要彻底理解SQL查询语句的执行顺序,我来简单举个例子各位应该就会明白了。

比如说现在我有一张员工部门表有一万条数据,并对部门进行分组,分组之后我还要查员工年龄大于35岁并且平均工资最高的那个部门的信息。

(1)先使用 WHERE 再使用 HAVING

大家想一下,如果先我们使用了 WHERE 过滤条件,假设 WHERE 过滤条件是大于35岁吧,那都是老员工了,条件也比较苛刻,经过我们 WHERE 之后,一万条数据只剩下了 500 条数据,这个时候我们再去对这 500 条数据去分组,再去求最大值,要做的事情会很少,性能就可以提升一大截。

(2)不使用 WHERE,只使用 HAVING

如果我不使用 WHERE 条件去过滤,我们将年龄的过滤条件为了省事也写到 HAVING 后面去过滤,这个时候就会有一个问题,因为 HAVING 是在分组操作执行之后才去做的,那么我们就会把这一万条数据全部进行分组,哐哐一顿分过组之后发现,我们只要年龄大于 35 岁的,那么我们前面对另外那 9500 条数据做的全部都是无用功,因为我们根本不需要,这样是不是会非常耗费系统的性能,这样来说明,相信大家对 WHERE 基于会有一个全新的认识了。

6.4 SQL的执行顺序为什么要这样设计呢?

不知道你们有没有发现,我在讲述 SQL 查询语句执行顺序的时候,多次强调底层有一张虚拟表,并强调这张虚拟表的数据越来越小。

各位想,数据越少,我们对数据进行操作时耗费的时间也越少,性能是不是越高啊!!!

我们多表查询时的第一次过滤 ON 过滤掉了大量的无用的笛卡尔积数据;

第二次条件过滤 WHERE 过滤掉了大量不满足条件的无用数据;

第三次条件过滤 HAVING 更多是为了使用聚合函数,又过滤掉了少量的无用数据;

这三次过滤,都是在底层虚拟表上进行行数据的过滤,各位能听懂吧,就是对这个虚拟表的每一行数据进行过滤;过滤完成之后,我们又进行的 SELECT 过滤,对我们需要的列数据又进行了一次过滤,取出我们想要的列数据,经过 SELECT 之后,我们又采用 DISTINCT 再次对重复的行数据进行过滤,经过层层严苛的筛选过滤,底层的那张虚拟表数据其实已经非常少了,各位可能会觉得很麻烦,这里我再次强调,数据量小的时候,对数据进行操作的速度是非常非常快的,因此SQL查询语句的执行顺序都是有逻辑可循的,各位同学可以再仔细揣摩揣摩,多思考几遍。

总而言之,言而总之,就一句话。SQL 查询语句执行顺序之所以这样设计,最终目的都是为了提高数据的查询效率与操作效率,避免做无用功。

你可能感兴趣的:(数据库,sql)