sql先执行from再执行select,根本原因是数据流必须从源头开始:from加载表、完成join生成初始行集,后续where、group by、select等操作均基于此原料库加工;select负责结果定义而非启动查询。

SQL先执行 FROM 再执行 SELECT,根本原因在于:数据库必须先知道“数据从哪来”,才能决定“要取哪些字段、怎么计算、怎么呈现”。这不是语法习惯,而是逻辑依赖——SELECT 依赖 FROM 提供的数据集,没有数据源,就无从选择。
数据流必须从源头开始
数据库执行查询不是“照着写的顺序读”,而是按数据生成的自然流程推进:
- FROM 阶段加载表、完成 JOIN、生成初始行集(哪怕上亿行),这是整个查询的“原料库”
- 后续所有操作(WHERE 过滤、GROUP BY 分组、SELECT 投影)都基于这个原料库进行加工
- 如果先跑 SELECT,它连“u.name”指的是哪张表的 name 都不确定,更无法解析别名或表达式
SELECT 是“最后定型”,不是“最先启动”
SELECT 看似写在最前面,实际承担的是“结果定义”角色:
- 它负责计算表达式(如
price * 1.1)、起别名(AS final_price)、调用聚合函数(COUNT(*)) - 但这些动作只能发生在分组(GROUP BY)之后、排序(ORDER BY)之前——因为 COUNT 需要已分好的组,别名要等字段确定后才存在
- 所以 SELECT 不是起点,而是中间加工环节的“出口定义”
违反顺序会直接报错
典型错误就是误把 SELECT 的逻辑前置使用:
-
WHERE user_name = 'Alice'✅ 可以,只要 user_name 在 FROM 的表里存在 -
WHERE full_name = 'Alice'❌ 报错,如果full_name是 SELECT 里用CONCAT(first, last) AS full_name定义的别名——WHERE 执行时它还不存在 -
HAVING AVG(score) > 80✅ 可以,HAVING 在 GROUP BY 之后、SELECT 之前,能访问聚合结果
优化器也遵循这个链条
即使数据库自动重排 JOIN 顺序或下推过滤条件,它也不会跳过 FROM 启动数据流:
- 优化器可能把 WHERE 条件“下推”到 JOIN 过程中提前过滤,但前提是:它已经通过 FROM 知道有哪些表、有哪些索引可用
- 没有 FROM,优化器连扫描范围都划不出来;没有 WHERE,它可能得全表扫;但没有 SELECT,它只是不输出——数据已在内存里流过了










