Appearance
SQL SELECT 语句逻辑执行顺序详解
💡 核心理念
与大多数编程语言按编码顺序处理代码不同,SQL 是一种声明式语言,其处理顺序与书写顺序大相径庭。理解 SQL 的逻辑执行顺序是编写高效查询、解决复杂 Join 和聚合问题的基础。
1. 逻辑执行顺序概览
虽然我们在编写 SQL 时以 SELECT 开头,但数据库引擎首先处理的是数据源(FROM)。
1.1 标准执行序列
- FROM: 组装数据源。
- ON: 应用联接筛选器。
- JOIN: 处理关联表(如 LEFT JOIN 补齐外部行)。
- WHERE: 对记录行进行初次筛选。
- GROUP BY: 将数据划分为多个分组。
- AGGREGATIONS: 执行聚合函数计算。
- HAVING: 筛选分组结果。
- SELECT: 确定返回的字段。
- DISTINCT: 行去重。
- ORDER BY: 对结果集进行排序。
- TOP / OFFSET-FETCH: 截取指定数量的行。
2. 逻辑查询处理阶段详解
在 SQL Server 中,每个步骤都会产生一个虚拟表 (Virtual Table, VT),该表作为下一步骤的输入。
| 步骤 | 子句 | 处理逻辑 | 产出 |
|---|---|---|---|
| Step 1 | FROM | 对前两个表执行笛卡尔积(交叉联接)。 | VT1 |
| Step 2 | ON | 对 VT1 应用 ON 筛选器,仅保留满足条件的行。 | VT2 |
| Step 3 | OUTER JOIN | 如果是外部联接,将保留表中未匹配的行作为外部行添加回 VT2。 | VT3 |
| Step 4 | WHERE | 对 VT3 应用 WHERE 筛选器,过滤掉不符合条件的记录。 | VT4 |
| Step 5 | GROUP BY | 按指定的列对 VT4 中的行进行分组。 | VT5 |
| Step 6 | CUBE / ROLLUP | 如果指定了超组运算,则生成相应的汇总行。 | VT6 |
| Step 7 | HAVING | 对分组后的 VT6 应用筛选器。 | VT7 |
| Step 8 | SELECT | 处理选择列表,计算表达式,提取最终字段。 | VT8 |
| Step 9 | DISTINCT | 移除 VT8 中的重复行。 | VT9 |
| Step 10 | ORDER BY | 根据指定的列对 VT9 进行排序,产生游标(而非表)。 | VC10 |
| Step 11 | TOP | 从 VC10 的起始处截取指定行数。 | VT11 |
3. 关键知识点与避坑指南
🔴 别名的可用性 由于 SELECT 在 WHERE 和 GROUP BY 之后执行,因此在 WHERE 子句中无法使用 SELECT 中定义的列别名。
🟡 WHERE 与 HAVING 的区别
WHERE作用于GROUP BY之前,过滤的是原始行。HAVING作用于GROUP BY之后,过滤的是聚合后的分组。
🟢 性能优化启示 尽量在 WHERE 阶段过滤掉尽可能多的数据,以减小后续 GROUP BY 和 JOIN 操作的虚拟表体积。
✅ 执行顺序简记口诀
FROM -> ON -> JOIN -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> ORDER BY -> TOP
🔗 参考资料
