标准执行顺序
mysql在执行一条select查询时,逻辑上的执行顺序如下:
from → where → group by → having → select → distinct → order by → limit
让我详细解释每个阶段:
1. from阶段
首先确定数据来源,包括表连接操作。如果有join,会先执行笛卡尔积或根据join条件进行表连接。多个表的join按从左到右的顺序执行。
2. where阶段
对from阶段产生的结果集进行条件过滤,筛选出符合条件的行。此时还不能使用select中定义的别名,因为select还没执行。
3. group by阶段
按照指定的列对数据进行分组,为聚合函数的计算做准备。
4. having阶段
对分组后的结果进行过滤,通常与聚合函数配合使用。having可以使用select中的别名(某些mysql版本支持)。
5. select阶段
选择要返回的列,执行计算、函数调用等操作,生成最终的列。
6. distinct阶段
如果有distinct关键字,对结果集去重。
7. order by阶段
对结果集进行排序。可以使用select中定义的别名。
8. limit阶段
限制返回的行数,通常用于分页。
常见场景示例
场景1:基础查询
select name, age from users where age > 18 order by age desc limit 10;
执行顺序:from users → where age > 18 → select name, age → order by age desc → limit 10
场景2:聚合查询
select department, count(*) as emp_count, avg(salary) as avg_salary from employees where status = 'active' group by department having count(*) > 5 order by avg_salary desc;
执行顺序:from employees → where status = ‘active’ → group by department → having count() > 5 → select department, count(), avg(salary) → order by avg_salary desc
场景3:多表join
select u.name, o.order_date, o.amount from users u inner join orders o on u.id = o.user_id where o.order_date > '2025-01-01' order by o.order_date desc;
执行顺序:from users u → inner join orders o → where o.order_date > ‘2025-01-01’ → select u.name, o.order_date, o.amount → order by o.order_date desc
场景4:子查询
select name, salary from employees where salary > (select avg(salary) from employees) order by salary desc;
执行顺序:先执行子查询得到平均工资 → from employees → where salary > 子查询结果 → select name, salary → order by salary desc
场景5:distinct去重
select distinct city from customers where country = 'china' order by city;
执行顺序:from customers → where country = ‘china’ → select city → distinct → order by city
场景6:复杂的多表关联与分组
select d.name as dept_name, count(e.id) as employee_count from departments d left join employees e on d.id = e.department_id and e.status = 'active' where d.region = 'east' group by d.id, d.name having employee_count > 0 order by employee_count desc limit 5;
执行顺序:from departments d → left join employees e (包含on条件) → where d.region = ‘east’ → group by d.id, d.name → having employee_count > 0 → select d.name, count(e.id) → order by employee_count desc → limit 5
重要注意事项
where vs having的区别:where在分组前过滤,不能使用聚合函数;having在分组后过滤,可以使用聚合函数。
别名的使用限制:where子句中不能使用select中定义的别名,因为where先于select执行。但order by和having可以使用别名。
join的on条件:在from阶段执行,早于where条件,因此在left join中,on条件和where条件的效果可能不同。
子查询的执行:相关子查询可能会对外层查询的每一行都执行一次,非相关子查询通常只执行一次。
理解这个执行顺序对编写高效sql、理解查询结果以及优化查询性能都非常重要。
以上就是mysql查询sql语句的执行顺序的方法的详细内容,更多关于mysql查询sql语句执行顺序的资料请关注代码网其它相关文章!
发表评论