网站首页 > 文章精选 正文
在 MySQL 中,SQL 语句的执行顺序并非完全按照书写顺序进行,而是遵循一套逻辑处理流程。以下是 SQL 查询语句的典型执行顺序(以 SELECT 语句为例),帮助理解查询如何被解析和执行:
1. 完整 SQL 语句的书写顺序
SELECT [DISTINCT] <字段列表>
FROM <表名>
[INNER|LEFT|RIGHT JOIN <表名> ON <连接条件>]
WHERE <过滤条件>
GROUP BY <分组字段>
HAVING <分组后过滤条件>
ORDER BY <排序字段>
LIMIT <分页限制>;
2. 实际执行顺序
MySQL 的执行引擎会按以下步骤处理查询(从数据源到结果集):
顺序 | 步骤 | 说明 |
1 | FROM | 确定数据来源,加载表或子查询的数据。 |
2 | ON | 处理 JOIN 的连接条件(筛选符合条件的行)。 |
3 | JOIN | 将关联表的数据合并到主表中(如 LEFT JOIN 保留左表所有行)。 |
4 | WHERE | 对合并后的数据行进行过滤(不可使用 SELECT 中的别名或聚合函数)。 |
5 | GROUP BY | 按指定字段分组(通常伴随聚合函数如 SUM()、COUNT())。 |
6 | HAVING | 对分组后的结果进行过滤(可使用聚合函数和 SELECT 中的别名)。 |
7 | SELECT | 选择最终输出的字段(可定义别名,执行计算或调用函数)。 |
8 | DISTINCT | 去重(若使用了 DISTINCT 关键字)。 |
9 | ORDER BY | 对结果集排序(可使用 SELECT 中的别名)。 |
10 | LIMIT/OFFSET | 限制返回的行数(如分页查询)。 |
3. 关键细节说明
(1) WHERE 与 HAVING 的区别
- WHERE:在分组前过滤数据,不可使用聚合函数(如 SUM())。
- SELECT user_id, COUNT(*) AS cnt FROM orders WHERE amount > 100 -- 先过滤金额大于100的订单 GROUP BY user_id;
- HAVING:在分组后过滤数据,可使用聚合函数。
- SELECT user_id, COUNT(*) AS cnt FROM orders GROUP BY user_id HAVING cnt > 5; -- 筛选订单数超过5的用户
(2) 别名的作用域
- SELECT 别名:只能在 HAVING、ORDER BY、LIMIT 中使用,不能在 WHERE 或 GROUP BY 中使用。
- -- 正确示例 SELECT amount * 0.9 AS discount FROM products ORDER BY discount; -- ORDER BY 可使用别名 -- 错误示例 SELECT amount * 0.9 AS discount FROM products WHERE discount > 100; -- WHERE 不能使用别名
(3) 子查询的执行顺序
- FROM 中的子查询:优先执行,生成临时表供主查询使用。
- SELECT * FROM (SELECT id, name FROM users WHERE age > 18) AS adult_users -- 先执行子查询 WHERE name LIKE 'A%';
- WHERE 中的子查询:在 WHERE 阶段执行。
- SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE vip = 1); -- 先执行子查询
4. 示例分析
SELECT
user_id,
COUNT(*) AS order_count
FROM orders
WHERE status = 'completed'
GROUP BY user_id
HAVING order_count > 3
ORDER BY order_count DESC
LIMIT 10;
执行流程:
- FROM orders:加载 orders 表数据。
- WHERE status = 'completed':过滤出状态为“已完成”的订单。
- GROUP BY user_id:按用户分组。
- HAVING order_count > 3:筛选订单数超过3的用户。
- SELECT user_id, COUNT(*) AS order_count:计算每个用户的订单数并命名别名。
- ORDER BY order_count DESC:按订单数降序排序。
- LIMIT 10:返回前10条结果。
5. 性能优化建议
- 优先使用 WHERE 过滤数据:减少 GROUP BY 处理的数据量。
- 为 WHERE 和 JOIN 条件字段建立索引:加速数据过滤和连接。
- 避免在 WHERE 中使用复杂计算或函数:可能导致索引失效。
- 合理使用 EXPLAIN:分析执行计划,优化查询逻辑。
总结:理解 SQL 执行顺序有助于编写高效查询,避免因逻辑错误导致性能问题或结果不符合预期。
可以记 where group having select 这个顺序即可,简化记忆
猜你喜欢
- 2025-05-09 面试必问的 MySQL 四种隔离级别,看完吊打面试官
- 2025-05-09 面试官:mysql自增长id用完了怎么办?这是我见过最中肯的答案了
- 2025-05-09 阿里面试:MySQL Binlog有哪些格式?底层原理?优缺点?
- 2025-05-09 1.5万字+30张图盘点程序员面试必会MySQL索引常见的11个知识点
- 2025-05-09 面试中的老大难-mysql事务和锁,一次性讲清楚
- 2025-05-09 手把手指导Linux系统centos7安装数据库MySQL5.7
- 2025-05-09 面试官问我MySQL索引为啥用B+树?我让他去问作者
- 2025-05-09 MySQL面试题:自增ID达到上限了会出现什么问题?
- 2025-05-09 MySQL索引失效问题,看完手撕面试官
- 2025-05-09 阿里面试:MySQL死锁的原因?解决方案有哪些?
- 最近发表
-
- Vue3+Django4全新技术实战全栈项目|高清完结
- 工厂模式+策略模式消除 if else 实战
- 每天一个 Python 库:httpx异步请求,让接口测试飞起来
- 如何高效实现API接口的自动化测试?
- 前端工程化:从“手忙脚乱”到“从容协作”的进化记
- 使用C#创建服务端Web API(c#开发web服务器)
- SpringBoot之旅第四篇-web开发(springboot做web项目)
- 一文读懂SpringMVC(一文读懂新型政策性金融工具)
- Rust Web编程:第十二章 在 Rocket 中重新创建我们的应用程序
- Apache Druid 数据摄取——本地数据和kafka流式数据 一篇文章看懂
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)