SQL执行顺序为FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY→LIMIT,而非书写顺序;FROM先加载数据并连接,WHERE过滤行,GROUP BY分组聚合,HAVING过滤分组,SELECT计算输出列并去重,ORDER BY排序,LIMIT截取结果。

SQL查询语句的执行顺序和书写顺序是两回事——你写的是 SELECT ... FROM ... WHERE ...,但数据库真正执行时,是从 FROM 开始,一步步筛选、计算、去重,最后才生成结果列。理解这个流程,能帮你写出更高效、更准确的SQL,也能快速定位“为什么查不到数据”或“为什么报错”。
FROM:先确定数据来源
执行的第一步是加载基础数据表(或视图、子查询),完成表连接(JOIN)。如果有多个表,数据库会按语法顺序或优化器策略决定连接方式(如嵌套循环、哈希连接)。此时还没过滤、没计算,只是把原始行组合起来。
- 如果
FROM后跟了子查询(如(SELECT ...)),该子查询会先执行并生成临时结果集,再作为“表”参与后续步骤 -
ON条件在JOIN过程中起作用,用于匹配左右表的行;它比WHERE更早生效,且对LEFT JOIN的右表空值保留至关重要 - 别名(
AS t1)在此阶段生效,后续所有步骤都只能用别名引用该表
WHERE:第一次行级过滤
在 FROM 和 JOIN 产出的临时结果集上,应用 WHERE 条件进行筛选。这一步只保留满足条件的行,不满足的整行被丢弃。
-
WHERE不能使用SELECT中定义的列别名(因为还没到SELECT阶段),也不能用聚合函数(如COUNT()),除非配合GROUP BY - 建议把高选择性条件(能大幅减少行数的)放在
WHERE前面,有助于优化器制定更优执行计划 -
NULL判断需用IS NULL或IS NOT NULL,不能用= NULL
GROUP BY & 聚合计算:分组与汇总
对 WHERE 筛选后的结果按指定列分组,然后对每组计算聚合值(如 SUM()、AVG()、COUNT())。这一步输出的是“组”而不是原始行。
-
GROUP BY后的列,或聚合函数内的列,才能出现在SELECT中(否则报错,如 MySQL 严格模式) -
HAVING在此阶段后立即执行,用于过滤分组结果(例如HAVING COUNT(*) > 5),它能引用聚合函数,而WHERE不能 - 没有
GROUP BY时,整个结果集被视为一个组,聚合函数作用于全部数据
SELECT 与 DISTINCT:决定最终输出列
这是逻辑上倒数第二步:计算 SELECT 列表中的表达式(包括列名、别名、函数、运算等),并可选地去重(DISTINCT)。
- 列别名在此处定义,并在后续步骤(如
ORDER BY)中可用;但WHERE和GROUP BY中不可用 -
DISTINCT是在所有SELECT表达式计算完成后,对整行结果去重,开销较大,应避免在大结果集上滥用 - 窗口函数(如
ROW_NUMBER() OVER(...))也在此阶段计算,但它们不改变行数,只增加计算列
ORDER BY 与 LIMIT:排序与截取
最后两步:先按指定列或表达式排序(升序 ASC 或降序 DESC),再取前 N 行(LIMIT / TOP / FETCH FIRST,依数据库而异)。
-
ORDER BY可以引用SELECT中的列别名、位置序号(如ORDER BY 2表示第二列),甚至未出现在SELECT中的列(只要它在FROM结果里存在) -
LIMIT(或等效语法)必须放在最后,否则语法错误;它作用于已排序的结果,不是原始数据 - 注意:无
ORDER BY时,LIMIT返回的行顺序是不确定的,不要依赖默认顺序
掌握这个执行顺序,你就知道为什么 WHERE 不能写聚合、为什么 ORDER BY 能用别名、为什么 LEFT JOIN 加 WHERE 条件可能变成交叉过滤。不复杂但容易忽略。










