简单讲解SQL执行顺序

本文详细介绍了SQL语句的标准执行流程,包括FROM&JOIN确定表连接,WHERE过滤数据,GROUP BY分组,HAVING进行聚合筛选,SELECT选择字段,DISTINCT去重,以及ORDER BY和LIMIT进行排序和限制。通过实例解析了每个步骤的作用和顺序,强调了LIMIT在查询中的重要性。理解这些步骤有助于优化SQL查询并提升数据库操作效率。

一条标准得SQL语句结构如下:
在这里插入图片描述

上面实际执行得过程为:

  • 我们先执行from,join来确定表之间的连接关系,得到初步的数据
  • where对数据进行普通的初步的筛选
  • group by 分组
  • 各组分别执行having中的普通筛选或者聚合函数筛选。
  • 然后把再根据我们要的数据进行select,可以是普通字段查询也可以是获取聚合函数的查询结果,如果是集合函数,select的查询结果会新增一条字段
  • 将查询结果去重distinct
  • 最后合并各组的查询结果,按照order by的条件进行排序
  • 在这里插入图片描述

数据的关联过程

数据库中的两张表
在这里插入图片描述

from & join & where

用于确定我们要查询的表的范围,涉及哪些表。另外,最新最全的 MySQL 面试题整理好了,微信搜索Java面试库小程序在线刷题。

选择一张表,然后用join连接:

from table1 join table2 on table1.id=table2.id

选择多张表,用where做关联条件

from table1,table2 where table1.id=table2.id

我们会得到满足关联条件的两张表的数据,不加关联条件会出现笛卡尔积。
在这里插入图片描述

group by

按照我们的分组条件,将数据进行分组,但是不会筛选数据。

比如我们按照即id的奇偶分组:
在这里插入图片描述

having & where

having中可以是普通条件的筛选,也能是聚合函数。而where只能是普通函数,一般情况下,有having可以不写where,把where的筛选放在having里,SQL语句看上去更丝滑。

使用where再group by

先把不满足where条件的数据删除,再去分组;

使用group by再having

先分组再删除不满足having条件的数据,这两种方法有区别吗,几乎没有!

举个例子:

100/2=50,此时我们把100拆分(10+10+10+10+10…)/2=5+5+5+…+5=50,
只要筛选条件没变,即便是分组了也得满足筛选条件,所以where后group by 和group by再having是不影响结果的!

不同的是,having语法支持聚合函数,其实having的意思就是针对每组的条件进行筛选。我们之前看到了普通的筛选条件是不影响的,但是having还支持聚合函数,这是where无法实现的。

当前数据分组情况:
在这里插入图片描述
执行having的筛选条件,可以使用聚合函数。筛选掉工资小于各组平均工资的 having salary < avg(salary)
在这里插入图片描述

select

分组结束之后,我们再执行select语句,因为聚合函数是依赖于分组的,聚合函数会单独新增一个查询出来的字段,这里用紫色表示,这里我们两个id重复了,我们就保留一个id,重复字段名需要指向来自哪张表,否则会出现唯一性问题。最后按照用户名去重。

select employee.id,distinct name,salary, avg(salary)

在这里插入图片描述
将各组having之后的数据再合并数据。

在这里插入图片描述

order by

最后我们执行order by 将数据按照一定顺序排序,比如这里按照id排序。如果此时有limit那么查询到相应的我们需要的记录数时,就不继续往下查了。
在这里插入图片描述

limit

记住limit是最后查询的,为什么呢?假如我们要查询年级最小的三个数据,如果在排序之前就截取到3个数据。实际上查询出来的不是最小的三个数据而是前三个数据了,记住这一点。

我们如果limit 0,3窃取前三个数据再排序,实际上最少工资的是2000,3000,4000。你这里只能是4000,5000,8000了。
在这里插入图片描述
以上为个人经验,希望能给大家一个参考,如有错误或未考虑完全的地方,望不吝赐教!

<think>好的,我现在需要帮助用户了解SQL执行顺序,并通过实例进行详细解析。用户之前提到了几个引用,我需要结合这些引用来构建回答。 首先,我需要回忆一下SQL语句的执行顺序。通常,SQL执行顺序并不是按照我们写查询的顺序来的,而是数据库优化器会按照特定的步骤来处理。比如,虽然SELECT写在最前面,但实际上执行的时候可能是在后面处理的。 接下来,我需要确定正确的执行步骤。常见的顺序应该是:FROM → ON → JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT/OFFSET。不过,不同的数据库系统可能会有些微差异,但总体流程类似。 然后,我需要找一个合适的例子来演示这个过程。用户提供的引用中有一个例子是“select * from T where ID=10”,可能可以用这个作为基础。或者自己构造一个稍微复杂点的例子,包含JOIN、WHERE、GROUP BY、HAVING等子句,这样能更全面地展示执行顺序。 现在,结合用户提供的引用,引用3提到了词法分析的过程,分解出关键字、表名、列名等。引用1提到了解析SELECT语句时,SQLSelectStatement会保存相关的语法树节点,比如查询的列、表名、条件等。引用2则涉及动态SQL的解析,可能和预处理阶段有关。不过用户的问题更关注执行顺序,所以可能需要重点引用1和3。 接下来,我需要详细分解每个步骤,并对应到实例中。例如,在实例中,先执行FROM确定数据来源,然后JOIN连接表,接着应用WHERE过滤,再进行GROUP BY分组,之后处理HAVING,选择列,去重,排序,最后限制结果数量。每个步骤都要用实例中的具体部分来说明。 同时,需要注意用户要求使用中文回答,数学表达式用$...$格式,独立公式用$$...$$,但在这个问题中可能数学公式较少,更多是步骤说明。但如果有涉及表达式的地方,比如聚合函数中的计算,可能需要用LaTeX格式。 另外,用户要求生成相关问题,我需要根据内容提出几个相关的问题,比如执行顺序的原理、优化器的影响、如何查看执行计划等。 最后,确保回答结构清晰,分步骤讲解,结合实例,并正确引用提供的资料。比如在解析FROM的时候提到引用3中的词法分析,或者在处理子查询时提到引用1中的语法树节点保存信息。</think>### SQL 执行顺序及实例解析 SQL执行顺序并非按书写顺序执行,而是由数据库优化器根据逻辑处理阶段动态调整。以下是典型的执行顺序及示例解析: --- #### **1. 基础执行顺序** 1. **FROM**(确定数据来源) 从表或子查询中加载数据。若涉及多表,优先处理连接条件(如`JOIN`)[^3]。 **示例**:`FROM employees e JOIN departments d ON e.dept_id = d.id` 2. **WHERE**(行级过滤) 筛选满足条件的记录,*不涉及聚合函数*。 **示例**:`WHERE e.salary > 5000` 3. **GROUP BY**(分组聚合) 按指定列分组,通常与聚合函数(如`SUM`、`COUNT`)配合使用。 **示例**:`GROUP BY d.name` 4. **HAVING**(分组后过滤) 对聚合后的结果进行筛选。 **示例**:`HAVING COUNT(e.id) > 10` 5. **SELECT**(选择列) 确定最终输出的列,可能包含计算字段或别名。 **示例**:`SELECT d.name AS dept_name, AVG(e.salary)` 6. **ORDER BY**(排序) 按指定规则排序结果集。 **示例**:`ORDER BY AVG(e.salary) DESC` 7. **LIMIT/OFFSET**(限制结果) 控制返回的行数。 **示例**:`LIMIT 10` --- #### **2. 实例解析** **示例 SQL**: ```sql SELECT d.dept_name, AVG(e.salary) AS avg_salary FROM employees e JOIN departments d ON e.dept_id = d.id WHERE e.join_year >= 2020 GROUP BY d.dept_name HAVING AVG(e.salary) > 8000 ORDER BY avg_salary DESC LIMIT 5; ``` **执行步骤分解**: 1. **FROM + JOIN** 加载`employees`和`departments`表,按`dept_id`连接,生成临时数据集。 2. **WHERE** 过滤`join_year >= 2020`的员工记录。 3. **GROUP BY** 按部门名称`d.dept_name`分组。 4. **HAVING** 筛选平均工资超过 8000 的部门。 5. **SELECT** 提取部门名称和平均工资,并为`AVG(e.salary)`设置别名`avg_salary`[^1]。 6. **ORDER BY** 按`avg_salary`降序排列。 7. **LIMIT** 仅返回前 5 条结果。 --- #### **3. 关键注意事项** - **优化器影响**:实际执行顺序可能因索引、统计信息等调整。 - **子查询处理**:嵌套子查询可能被优化器重写为连接操作[^2]。 - **执行计划查看**:通过`EXPLAIN`命令可获取具体数据库(如MySQL)的执行顺序[^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值