百度一面:SQL的执行顺序是怎样的?

发布于:2025-03-29 ⋅ 阅读:(27) ⋅ 点赞:(0)

在MySQL中,SQL语句的执行顺序与书写顺序不同,理解这一点对编写高效查询和排查问题至关重要。以下是详细说明及示例:


SQL执行顺序(逻辑处理阶段)

  1. FROM & JOIN

    • 确定数据来源,处理表连接,生成初始数据集。
    • 子查询在此阶段执行,形成临时表。
  2. WHERE

    • 过滤行级数据,排除不满足条件的行。
    • 注意:聚合函数(如SUM)不能在此阶段使用。
  3. GROUP BY

    • 按指定列分组,为聚合计算做准备。
  4. HAVING

    • 过滤分组后的数据,只能使用GROUP BY中的列或聚合函数。
    • 注意:严格按标准SQL,不能直接使用SELECT中的别名,但MySQL允许部分例外。
  5. SELECT

    • 选择最终输出的列,计算表达式,生成别名。
    • 窗口函数在此阶段处理。
  6. DISTINCT

    • 去重操作,基于SELECT的结果集。
  7. ORDER BY

    • 按指定列排序,可使用SELECT中的别名。
  8. LIMIT & OFFSET

    • 分页操作,限制返回的行数。

示例拆解

查询需求

找出2023年订单总金额超过1000的用户,按总金额降序取前10名。

SQL语句

SELECT
    u.user_id,
    SUM(o.amount) AS total_amount
FROM
    users u
JOIN orders o ON u.user_id = o.user_id
WHERE
    o.order_date >= '2023-01-01'
GROUP BY
    u.user_id
HAVING
    total_amount > 1000
ORDER BY
    total_amount DESC
LIMIT 10;

执行步骤分析

  1. FROM & JOIN

    • 先执行FROM usersJOIN orders,将usersorders表连接,生成包含所有匹配行的临时表。
  2. WHERE

    • 过滤order_date >= '2023-01-01'的订单,排除非2023年的数据。
  3. GROUP BY

    • user_id分组,每个用户的所有订单被聚合为一组。
  4. HAVING

    • 过滤分组后total_amount > 1000的用户。
    • 注意:此处total_amountSUM(o.amount)的别名,MySQL允许这种写法,但标准SQL需直接使用SUM(o.amount) > 1000
  5. SELECT

    • 计算每个用户的SUM(o.amount),并赋予别名total_amount
  6. ORDER BY

    • total_amount降序排列结果。
  7. LIMIT

    • 返回前10条记录。

关键注意事项

  • 别名作用域

    • WHEREHAVING中不能直接使用SELECT中的别名(MySQL部分支持,但依赖数据库实现)。
    • ORDER BYLIMIT可以使用别名,因为它们执行在SELECT之后。
  • 性能优化

    • 尽量在WHERE中提前过滤数据,减少GROUP BYHAVING处理的数据量。
    • 避免在WHEREJOIN中使用复杂表达式,可能影响索引使用。
  • 聚合函数与窗口函数

    • 聚合函数(如SUM)在GROUP BY后生效。
    • 窗口函数(如ROW_NUMBER())在SELECT阶段处理,但可配合OVER()在分组后计算。

通过理解执行顺序,可以更高效地编写查询,并避免因逻辑错误导致的性能问题或结果异常。