MySQL SQL 执行顺序(理论顺序)
示例 SQL:
SELECT name, COUNT(*)
FROM users
WHERE age > 18
GROUP BY name
HAVING COUNT(*) > 1
ORDER BY name ASC
LIMIT 10;
虽然语句是从 SELECT 写起的,但执行顺序其实是这样的:
| 执行顺序 | SQL 子句 | 作用说明 |
|---|---|---|
| ① | FROM | 确定查询的表、建立连接(JOIN) |
| ② | ON | 用于连接条件(如果有 JOIN) |
| ③ | JOIN | 执行表连接操作(如果有) |
| ④ | WHERE | 行过滤,只保留符合条件的记录 |
| ⑤ | GROUP BY | 分组操作 |
| ⑥ | HAVING | 分组后的条件过滤 |
| ⑦ | SELECT | 选择要查询的列或表达式 |
| ⑧ | DISTINCT | 去重操作(如果指定) |
| ⑨ | ORDER BY | 排序操作 |
| ⑩ | LIMIT | 限制返回结果的行数 |
📌 举例说明执行流程
SELECT department, COUNT(*) AS emp_count
FROM employees
WHERE salary > 5000
GROUP BY department
HAVING COUNT(*) > 2
ORDER BY emp_count DESC
LIMIT 5;
执行过程如下:
- FROM employees:确定数据源
- WHERE salary > 5000:筛选工资高于 5000 的员工
- GROUP BY department:按照部门分组
- HAVING COUNT(*) > 2:保留每组中人数超过 2 的部门
- SELECT department, COUNT(*):选择要显示的列
- ORDER BY emp_count DESC:按员工数倒序
- LIMIT 5:只取前 5 行
⚠️ 常见误区说明
WHERE是在分组前过滤,HAVING是在分组后过滤SELECT是在大多数逻辑完成后才进行,所以别名在WHERE中无法使用LIMIT是最后执行的,用于截取结果集
✅ 小技巧
| 需求 | 应该使用 |
|---|---|
| 筛选原始记录 | WHERE |
| 筛选分组结果 | HAVING |
| 连接多表时的条件 | ON |
| 排序字段来自聚合结果 | ORDER BY 中使用别名 |
可视化流程图

