sql执行顺序为FROM→WHERE→GROUP BY→HAVING→select→DISTINCT→ORDER BY→LIMIT,而非书写顺序;FROM最先加载数据源,WHERE过滤原始行,GROUP BY分组后HAVING筛选分组结果,SELECT才计算表达式和别名,最后ORDER BY排序、LIMIT截断。

SQL的SELECT语句看似简单,实际执行时并非按书写顺序运行。理解其真实执行顺序,是写出高效、正确查询的基础,也能帮你避开常见陷阱,比如WHERE中引用了SELECT里定义的别名、或GROUP BY和聚合函数配合出错等问题。
FROM:最先执行,确定数据源
无论你写多少表、用什么JOIN,数据库第一步永远是从FROM子句开始——加载基础表或视图,生成初始的笛卡尔积(如果有多表且没ON条件)。如果有子查询或CTE(WITH),也会在此阶段完成物化或展开。
- 多表JOIN时,优化器可能重排表顺序,但逻辑上仍以FROM列出的表为起点
- 如果FROM中包含复杂的子查询,它会先执行完,结果作为临时“虚表”供后续步骤使用
- 注意:WHERE、GROUP BY等都不能影响FROM阶段的表加载,哪怕WHERE条件再严格,全表扫描仍可能在FROM阶段发生
WHERE → GROUP BY → HAVING:筛选与分组三步连动
在FROM产出初始行集后,数据库立即应用WHERE过滤——这是第一个真正“减少数据量”的环节。接着按GROUP BY分组,再用HAVING对分组结果做二次筛选。这三者构成一个紧密的“分组前/后筛选链”。
- WHERE作用于原始行,不能用聚合函数(如SUM、count)或SELECT中的列别名
- GROUP BY必须包含SELECT中所有非聚合列(严格模式下),否则报错
- HAVING可引用聚合函数和GROUP BY字段,但不能引用WHERE未出现的非分组列
SELECT → DISTINCT → ORDER BY → LIMIT:最终呈现层
直到这时,SELECT才真正执行——计算表达式、取别名、去重(DISTINCT)、排序(ORDER BY)、截断(LIMIT/OFFSET)。这个阶段的数据已不可被WHERE或HAVING修改。
- SELECT中定义的别名,在WHERE、GROUP BY、HAVING中都不可用(因为它们早已执行完毕)
- ORDER BY可以引用SELECT中的别名或位置序号(如ORDER BY 1),但标准SQL更推荐用别名
- LIMIT不是SQL标准语法(mysql/postgresql支持,SQL Server用TOP,oracle用ROWNUM或FETCH FIRST),但它总在最后生效,不改变逻辑结果集大小,只控制返回行数
基本上就这些。记住:写的时候从SELECT开始顺手敲,跑的时候从FROM开始层层推进。搞清这个顺序,很多“为什么报错”“为什么结果不对”的问题就迎刃而解了。