MySQL 中 FROM、where、group by、having、select、distinct、order by、limit 执行的顺序 详细说明

无任何基础,不懂二进制,边学边做边挣钱,靠毅力从上而下【逆向钻研,逆练九阴真经】,经过山路十八弯,一言难尽,最终逆学成才。胸怀天下,下一个项目将直击天下人,革命,众神归位; / 2024-09-26 / 原文

在 MySQL 中,SQL 查询语句的执行顺序与书写顺序有所不同。了解这些关键字的执行顺序对于编写高效的查询语句至关重要。以下是这些关键字的执行顺序详细说明:

执行顺序

  1. FROM

    • 执行内容:首先,MySQL 确定查询的数据来源,即要查询的表。如果查询涉及多个表,MySQL 会根据表之间的连接关系(如 JOIN 操作)生成一个虚拟表,这个虚拟表包含了所有参与查询的表的数据行。
    • 注意事项:FROM 子句的执行顺序是从后往前、从右到左,即最后一个表(基础表或驱动表)会被最先处理。
  2. WHERE

    • 接下来,MySQL 会在 FROM 子句生成的结果集上应用 WHERE 子句的条件,以过滤掉不符合条件的记录。这一步是在数据分组之前进行的。
  3. GROUP BY

    • 执行内容:如果查询中包含了 GROUP BY 子句,MySQL 会根据指定的列将虚拟表中的数据行分组。分组后的每一组包含具有相同列值的所有行。
    • 注意事项:GROUP BY 子句的执行顺序是从左往右。在分组之后,可以使用聚合函数对每组数据进行计算。
  4. HAVING

    • 执行内容:HAVING 子句用于对 GROUP BY 分组后的结果进行过滤。与 WHERE 子句不同,HAVING 子句可以引用聚合函数。
    • 注意事项:HAVING 子句必须跟在 GROUP BY 子句之后,用于对分组后的结果进行条件筛选。
  5. SELECT

    • 执行内容:在选择要返回的列之前,所有的过滤和分组操作都已完成。此时,MySQL 根据 SELECT 子句中的列名和表达式从虚拟表中选择要返回的数据。
    • 注意事项:SELECT 子句中可以包含列名、聚合函数、计算表达式等。
  6. DISTINCT

    • 执行内容:如果查询中包含了 DISTINCT 关键字,MySQL 会在 SELECT 子句选择列之后,对结果进行去重处理。
    • 注意事项:DISTINCT 关键字通常放在 SELECT 子句的最前面,用于去除重复的记录。
  7. ORDER BY

    • 执行内容:在所有前面的步骤都完成后,MySQL 会根据 ORDER BY 子句中的列对结果进行排序。
    • 注意事项:ORDER BY 子句的执行顺序是从左到右。排序操作是非常消耗资源的,因此应尽量避免在大数据集上进行全表排序。
  8. LIMIT

    • 执行内容:最后,如果查询中包含了 LIMIT 子句,MySQL 会根据指定的数量限制返回的记录数。
    • 注意事项:LIMIT 子句通常用于分页查询,可以指定返回的记录数以及跳过的记录数。

总结

MySQL 查询语句的执行顺序是:

  1. FROM(确定数据来源)
  2. WHERE(对数据源进行过滤)
  3. GROUP BY(对过滤后的结果进行分组)
  4. HAVING(对分组后的结果进行条件筛选)
  5. SELECT(选择列和计算表达式)
  6. DISTINCT(去重)
  7. ORDER BY(排序)
  8. LIMIT(限制返回的记录数)

了解这些关键字的执行顺序有助于更好地理解查询语句的工作原理,并编写出更加高效、准确的查询语句。


WHERE 子句的执行顺序??

关于WHERE子句的执行顺序,实际上,MySQL在执行SQL语句时,并不会严格按照书写顺序(即从左到右或从右到左)来逐一评估WHERE子句中的条件。MySQL的优化器会分析WHERE子句中的所有条件,并尝试找到最优的执行计划。这意味着,即使你将条件写在WHERE子句的最右边,如果优化器认为先评估另一个条件会更高效,它也会相应地调整执行顺序。

然而,有一个普遍接受的观点是,将那些能够过滤掉大量记录的条件放在WHERE子句的前面(或理解为在逻辑上优先评估这些条件),有助于优化器生成更有效的执行计划。因为这样做可以减少后续处理的数据量,从而提高查询效率。但请注意,这并不意味着MySQL总是按照这种顺序来执行条件。

下面,我将通过一个具体的例子来进一步说明这一点。

假设我们有一个名为employees的表,其中包含员工的姓名(name)、部门(department)和薪水(salary)等信息。现在,我们想要查询部门为"IT"且薪水高于5000的所有员工。

SQL查询语句可能如下所示:

SELECT * FROM employees WHERE department = 'IT' AND salary > 5000;

在这个例子中,虽然department = 'IT'salary > 5000两个条件在WHERE子句中的顺序是任意的,但如果department列上有索引,并且大多数员工都不属于"IT"部门,那么将department = 'IT'条件放在前面(或在逻辑上优先评估)可能有助于优化器更快地定位到需要处理的数据集。然而,这并不意味着MySQL总是按照这种顺序来执行条件。

为了验证或观察实际的执行顺序,我们可以使用MySQL的EXPLAIN命令来查看查询的执行计划。但请注意,EXPLAIN命令显示的是优化器选择的执行计划,而不是实际执行时的每一步操作。

此外,还需要强调的是,随着MySQL版本的更新和查询优化器的改进,执行计划可能会发生变化。因此,在编写SQL查询语句时,虽然考虑查询效率很重要,但也不必过分担心WHERE子句中条件的具体顺序。更重要的是,要确保查询逻辑正确,并合理利用索引来提高查询性能。

最后,需要指出的是,虽然有些资料或文章可能会提到WHERE子句的执行顺序是自下而上、从右到左的,但这通常是对SQL语句解析过程的一种简化描述,并不完全准确反映MySQL查询优化器的实际行为。在实际应用中,我们应该以MySQL官方文档和EXPLAIN命令提供的执行计划为准。