实用指南:SQL执行顺序

SQL语句的执行顺序并非严格按照书写顺序,而是遵循一套逻辑流程。理解这一顺序是编写高效查询和排查问题的关键。以下是完整执行阶段的详细解析,结合你的查询案例进行说明:

一、SQL执行顺序全阶段(按实际执行先后排序)

阶段序号关键字/操作作用说明
1FROM从指定表中读取原始数据,作为整个查询的数据源
2JOIN + ON关联其他表,根据ON条件合并数据(如LEFT JOIN保留左表所有记录)
3WHERE过滤行数据,仅保留满足条件的记录(不能使用聚合函数)
4GROUP BY将结果集按指定列分组,每组数据作为独立单元后续处理
5HAVING过滤分组数据,仅保留满足条件的分组(可使用聚合函数,如HAVING COUNT(*) > 10
6SELECT选择需要返回的列(包括计算列和别名),此时才会解析AS定义的别名
7DISTINCTSELECT结果去重(若使用)
8ORDER BY对最终结果按指定列排序(可使用SELECT中定义的别名)
9LIMIT限制返回的行数(如分页查询)

二、结合你的查询案例拆解执行步骤

SELECT
  Signups.user_id,
  ROUND(IFNULL(AVG(Confirmations.action = 'confirmed'), 0), 2) AS confirmation_rate
FROM Signups
LEFT JOIN Confirmations ON Signups.user_id = Confirmations.user_id
-- WHERE (此处无该子句)
GROUP BY Signups.user_id
-- HAVING (此处无该子句)
-- ORDER BY (此处无该子句)
1. FROM Signups
  • 操作:从Signups表读取所有用户的基础信息(如user_id)。
  • 输出[ {user_id: 1}, {user_id: 2}, ... ](仅含Signups表数据)。
2. LEFT JOIN Confirmations ON ...

  • 操作:根据user_id关联Confirmations表,保留Signups表所有用户,即使该用户无确认记录。
  • 输出
    [
      {user_id: 1, action: 'confirmed'},  // 有确认记录
      {user_id: 1, action: 'ignored'},     // 有确认记录
      {user_id: 2, action: NULL}           // 无确认记录(左连接补NULL)
    ]

3. GROUP BY Signups.user_id
  • 操作:按user_id将数据分组,每个用户成为独立组。
  • 输出
    组1(user_id=1): [ {action: 'confirmed'}, {action: 'ignored'} ]
    组2(user_id=2): [ {action: NULL} ]

4. SELECT 与聚合计算
  • 操作:对每个组执行AVG(Confirmations.action = 'confirmed')
    • 组1:(1 + 0) / 2 = 0.5 → ROUND(0.5, 2) = 0.50
    • 组2:IFNULL(AVG(NULL), 0) = 0 → ROUND(0, 2) = 0.00
  • 输出最终结果
    +---------+-------------------+
    | user_id | confirmation_rate |
    +---------+-------------------+
    | 1       | 0.50              |
    | 2       | 0.00              |
    +---------+-------------------+

三、关键注意事项

  1. WHERE vs HAVING

    • WHERE在分组前过滤,不能使用聚合函数(如WHERE AVG(...) > 0.5是错误的)。
    • HAVING在分组后过滤,可使用聚合函数(如HAVING confirmation_rate > 0.5)。
  2. 别名的可见性

    • SELECT中定义的别名(如confirmation_rate)只能在ORDER BYHAVING中使用,不能在WHEREGROUP BY中使用(因为执行顺序靠后)。
  3. SELECT的执行时机

    • SELECT倒数第4个执行的阶段,因此在书写复杂查询时,需注意早期阶段(如WHERE)无法引用SELECT中定义的计算列。

四、执行顺序与书写顺序对比

书写顺序(从上到下)实际执行顺序(从1到9)
SELECT6
FROM1
JOIN2
WHERE3
GROUP BY4
HAVING5
ORDER BY8
LIMIT9

五、记忆口诀

为方便记忆,可使用以下口诀:

“从(FROM)哪张表来,联(JOIN)哪些数据,过(WHERE)滤掉杂质,分(GROUP BY)成小组看,组内过(HAVING)滤,选(SELECT)出结果,去(DISTINCT)重,排(ORDER BY)个序,取(LIMIT)前几名。”

posted @ 2026-01-31 11:50  yangykaifa  阅读(0)  评论(0)    收藏  举报