【重学 MySQL】四十、SQL 语句执行过程

【重学 MySQL】四十、SQL 语句执行过程

  • [select 语句的完整结构](#select 语句的完整结构)
  • [select 语句执行顺序](#select 语句执行顺序)
  • [SQL 语句执行原理](#SQL 语句执行原理)

select 语句的完整结构

SELECT 语句是 SQL(Structured Query Language)中用于从数据库表中检索数据的核心语句。一个完整的 SELECT 语句结构可以包括多个部分,但并非所有部分都是必须的,具体取决于你想从数据库中检索什么信息。以下是一个相对完整的 SELECT 语句结构示例:

sql 复制代码
SELECT 
    [DISTINCT] column1, column2, ...
FROM 
    table_name
[WHERE condition]
[GROUP BY column1, column2, ...]
[HAVING condition]
[ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...]
[LIMIT number [OFFSET offset]];

这里是每个部分的简要说明:

  1. SELECT :指定要从表中检索的列。可以使用 * 来检索所有列。DISTINCT 关键字用于返回唯一不同的值。

  2. FROM:指定要从中检索数据的表名。

  3. WHERE(可选):指定过滤条件,用于限制哪些行应被包含在结果集中。

  4. GROUP BY(可选):将结果集中的行分组为一个或多个汇总行,每个分组包含列中值的集合。通常与聚合函数(如 COUNT, MAX, MIN, SUM, AVG)一起使用。

  5. HAVING(可选):类似于 WHERE,但用于过滤分组后的结果。它通常与 GROUP BY 一起使用,对聚合后的结果进行过滤。

  6. ORDER BY(可选):指定结果集的排序方式。可以指定一个或多个列进行排序,以及排序的方向(升序 ASC 或降序 DESC)。

  7. LIMIT (可选):限制返回的记录数。OFFSET 子句(如果与 LIMIT 一起使用)指定在开始返回记录之前要跳过的记录数。

请注意,并非每个 SELECT 语句都需要包含所有这些部分。实际上,大多数简单的查询只需要 SELECTFROM 部分。其他部分根据具体需求添加。

例如,一个简单的查询可能看起来像这样:

sql 复制代码
SELECT name, age
FROM users;

这个查询从 users 表中检索 nameage 列的所有数据。

select 语句执行顺序

SELECT语句的执行顺序在SQL中是一个重要的概念,它决定了数据库如何处理和返回查询结果。尽管在编写SQL语句时,我们可能按照SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...这样的顺序来书写,但实际上,数据库在执行这些语句时遵循的是不同的内部逻辑顺序。以下是SELECT语句的完整执行顺序:

  1. FROM/JOIN

    • 这是SQL语句执行的第一步。数据库首先根据FROM子句确定要从哪个表(或哪些表通过JOIN操作)中检索数据。如果使用了JOIN,则还会根据ON子句指定的条件来合并表。
  2. WHERE

    • 在确定了数据源之后,数据库会根据WHERE子句中的条件对记录行进行筛选,排除不满足条件的行。
  3. GROUP BY

    • 如果查询中包含了GROUP BY子句,则数据库会将筛选后的结果集按照指定的列进行分组。分组操作通常与聚合函数(如COUNT、SUM、AVG等)一起使用,以便对每个分组进行统计计算。
  4. 使用聚集函数进行计算

    • 在分组之后,数据库会对每个分组应用聚合函数进行计算,得到每个分组的统计信息。
  5. HAVING

    • HAVING子句用于对分组后的结果进行过滤。与WHERE子句不同,HAVING可以在过滤条件中使用聚合函数。
  6. 计算所有的表达式

    • 在此阶段,数据库会计算SELECT列表中指定的所有表达式,包括算术表达式、字符串函数等。
  7. SELECT的字段

    • 根据SELECT子句指定的列或表达式,从前面的结果集中选择最终的输出列。
  8. DISTINCT(如果指定了):

    • 如果在SELECT语句中使用了DISTINCT关键字,则数据库会对结果集进行去重操作,确保每个输出行都是唯一的。
  9. ORDER BY

    • 最后,如果查询中包含了ORDER BY子句,则数据库会根据指定的列对结果集进行排序。排序可以是升序(ASC)或降序(DESC)。
  10. LIMIT/OFFSET(如果指定了):

    • 如果查询中包含了LIMIT子句(可能还伴随着OFFSET子句),则数据库会限制返回的记录数,并可能跳过一定数量的记录。

需要注意的是,虽然这个顺序描述了数据库内部处理SQL语句的方式,但在编写SQL语句时,我们仍然应该按照逻辑顺序来书写,即先指定数据源(FROM/JOIN),然后设置筛选条件(WHERE),接着进行分组和聚合(GROUP BY、聚合函数),最后选择输出列(SELECT)和排序(ORDER BY)。这样做有助于保持SQL语句的清晰和可读性。

SQL 语句执行原理

SELECT 是先执行 FROM 这一步的。在这个阶段,如果是多张表联查,还会经历下面的几个步骤:

  1. 首先先通过 CROSS JOIN 求笛卡尔积,相当于得到虚拟表 vt(virtual table)1-1;
  2. 通过 ON 进行筛选,在虚拟表 vt1-1 的基础上进行筛选,得到虚拟表 vt1-2;
  3. 添加外部行。如果我们使用的是左连接、右链接或者全连接,就会涉及到外部行,也就是在虚拟表 vt1-2 的基础上增加外部行,得到虚拟表 vt1-3。

当然如果我们操作的是两张以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得到是我们的原始数据。

当我们拿到了查询数据表的原始数据,也就是最终的虚拟表 vt1,就可以在此基础上再进行 WHERE 阶段。在这个阶段中,会根据 vt1 表的结果进行筛选过滤,得到虚拟表 vt2

然后进入第三步和第四步,也就是 GROUP 和 HAVING 阶段。在这个阶段中,实际上是在虚拟表 vt2 的基础上进行分组和分组过滤,得到中间的虚拟表 vt3vt4

当我们完成了条件筛选部分之后,就可以筛选表中提取的字段,也就是进入到 SELECT 和 DISTINCT 阶段

首先在 SELECT 阶段会提取想要的字段,然后在 DISTINCT 阶段过滤掉重复的行,分别得到中间的虚拟表 vt5-1vt5-2

当我们提取了想要的字段数据之后,就可以按照指定的字段进行排序,也就是 ORDER BY 阶段,得到虚拟表 vt6

最后在 vt6 的基础上,取出指定行的记录,也就是 LIMIT 阶段,得到最终的结果,对应的是虚拟表 vt7

当然我们在写 SELECT 语句的时候,不一定存在所有的关键字,相应的阶段就会省略。

同时因为 SQL 是一门类似英语的结构化查询语言,所以我们在写 SELECT 语句的时候,还要注意相应的关键字顺序,所谓底层运行的原理,就是我们刚才讲到的执行顺序。

相关推荐
TuringSnowy1 分钟前
Groupby_SQL和pandas等效例子
数据库·sql·mysql·pandas
woshilys2 分钟前
sql server 版本补丁更新
数据库·sqlserver
白如意i24 分钟前
在Ubuntu 16.04上安装最新版本的MySQL的方法
linux·mysql·ubuntu
百成Java1 小时前
基于Spring Boot的旅游网站
java·开发语言·spring boot·后端·mysql
小城里的梦想1 小时前
redis和mysql端口修改
数据库·redis·mysql
光锥智能1 小时前
OceanBase云数据库战略实施两年,受零售、支付、制造行业青睐
数据库·oceanbase·零售
赤鸢QAQ1 小时前
pyqt瀑布流布局
数据库·pyqt
极客先躯2 小时前
高级java每日一道面试题-2024年9月29日-数据库篇-索引怎么定义,分哪几种?
java·数据结构·数据库·分类·索引·全文索引·聚集索引
F_D_Z2 小时前
【SQL】重复的邮箱信息
数据库·sql