示例 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 中使用别名 |