MySQL 的 SQL 语句执行顺序并不完全按照代码的书写顺序执行,而是遵循一套固定的逻辑流程
1. FROM 和 JOIN
作用:确定查询的数据来源,包括表和它们的连接方式(如
INNER JOIN
,LEFT JOIN
等)。细节:
先执行
FROM
,确定基础表。再执行
JOIN
,将多个表按条件连接,生成临时结果集(中间表)
2. WHERE
作用:对
FROM
/JOIN
生成的中间表进行过滤,筛选符合条件的行。细节:
不可使用 SELECT 中的别名:因为此时
SELECT
尚未执行。过滤效率高:尽早减少后续处理的数据量。
3. GROUP BY
作用:将数据按指定列分组,通常与聚合函数(如
SUM
,COUNT
)配合使用。细节:
分组后,每组生成一行汇总结果。
可以使用
GROUP BY column1, column2
多列分组。
4. HAVING
作用:对
GROUP BY
分组后的结果进行过滤。细节:
与 WHERE 的区别:
WHERE
过滤行,HAVING
过滤分组。可使用聚合函数:如
HAVING SUM(price) > 100
。
5. SELECT
作用:选择最终输出的列,并计算表达式或别名。
细节:
执行列的计算(如
price * quantity AS total
)。别名在此阶段生效:因此不能在
WHERE
中使用别名,但可在ORDER BY
中使用。
6. DISTINCT
作用:去除
SELECT
结果中的重复行。细节:
对最终结果去重,可能影响性能(需排序或哈希处理)。
7. ORDER BY
作用:按指定列排序结果。
细节:
默认升序(
ASC
),可指定降序(DESC
)。可使用 SELECT 别名:因为
SELECT
已执行
8. LIMIT / OFFSET
作用:限制返回的行数(如分页查询)。
细节:
LIMIT n
返回前n
行。LIMIT m, n
跳过m
行后返回n
行(或LIMIT n OFFSET m
)。
关键注意事项
别名的作用域:
SELECT
中定义的别名只能在ORDER BY
或HAVING
之后使用,不能在WHERE
或GROUP BY
中使用。示例:
SELECT price * quantity AS total
FROM orders
WHERE total > 100; -- 错误!WHERE 无法识别 total 别名
聚合函数的位置:
聚合函数(如
SUM
,AVG
)不能在WHERE
中使用,但可以在HAVING
或SELECT
中使用。示例:
SELECT user_id, SUM(price)
FROM orders
GROUP BY user_id
HAVING SUM(price) > 100; -- 正确
性能优化:
尽量在
WHERE
中提前过滤数据,减少GROUP BY
和JOIN
处理的数据量。
SELECT country, COUNT(*) AS user_count
FROM users
WHERE age > 18
GROUP BY country
HAVING user_count > 100
ORDER BY user_count DESC
LIMIT 10;
执行顺序:
FROM users
→ 读取users
表。WHERE age > 18
→ 过滤出年龄大于 18 的用户。GROUP BY country
→ 按国家分组。HAVING user_count > 100
→ 过滤出用户数超过 100 的国家。SELECT country, COUNT(*) AS user_count
→ 选择列并计算别名。ORDER BY user_count DESC
→ 按用户数降序排序。LIMIT 10
→ 返回前 10 行。