SQL 查询的执行顺序

这篇具有很好参考价值的文章主要介绍了SQL 查询的执行顺序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

by emanjusaka from ​ https://www.emanjusaka.top/2023/09/sql-query-order 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。

前言

了解 SQL 查询的执行顺序对我们解决一些问题很有帮助,有时我们可能会疑惑为什么不能对分组的结果进行筛选这样类似的问题?之前一直不是理解这个问题,在了解了SQL 查询的执行顺序之后这个问题也就迎刃而解。在我们对 SQL 查询语句进行分析优化时,掌握执行顺序也是有一定帮助的。

一、理论顺序

上面是图示 SQL 的执行顺序,下面用列表列出:

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. CUBE | ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. LIMIT

上面所列出的执行顺序能帮助我们解答一些问题:

  • 为啥不能对窗口函数的执行结果进行过滤?

    因为窗口函数在 SELECT 步骤执行,而这步是在 WHERE 和 GROUP BY 之后

  • 可以对分组的结果进行筛选吗?

    不可以,因为 GROUP BY 在 WHERE 之后执行

  • 可以对分组后的结果进行排序吗?

    可以,因为 ORDER BY 在 GROUP BY 之后。

二、代码示例

  • 学生表

  • 成绩表

  • 查询语句

    查询来自天津且总成绩高于70分,并且查询他们的总成绩,查询结果按成绩降序排列

    SELECT
    	ss.student_id,sum(se.grade) as total,ss.city
    FROM
    	students ss
    	LEFT JOIN score se ON ss.student_id = se.student_id 
    WHERE
    	ss.city = "天津"
    GROUP BY ss.student_id
    HAVING sum(se.grade) > 70
    ORDER BY total DESC
    LIMIT 10
    
  • 查询结果

三、分析 SQL 执行过程

SQL 运行的每个操作都会产生一张虚拟表,只不过这些虚拟表对用户是透明的,只有最后一步生成的虚拟表才会返回给用户。

  1. 第一步执行的是对 FROM 字句前后的两张表 students 和 score 进行笛卡尔积操作,生成虚拟表VT1。

  2. 应用 ON 过滤器

    在虚拟表 VT1 中执行过滤操作,过滤条件为:ss.student_id = se.student_id ​

    对于在 ON 过滤条件下的 NULL 值比较,此时的比较结果为 UNKNOWN,却被视为 FALSE 来进行处理,即两个 NULL 并不相同。但是在下面两种情况下认为两个 NULL 值的比较是相等的:

    • GROUP BY 子句把所有 NULL 值分到同一组
    • ORDER BY 子句中把所有 NULL 值排列在一起

    在产生虚拟表 VT2 时,会增加一个额外的列来表示 ON 过滤条件的返回值,返回值有 TRUE、FALSE、UNKNOWN。取出比较值为 TRUE 的记录,产生虚拟表 VT2。

  3. 添加外部行

    这一步只有在连接类型为 OUTER JOIN 时才发生,如 LEFT OUTER JOIN、RIGHT OUTERJOIN、FULL OUTER JOIN。虽然在大多数时候我们可以省略 OUTER 关键字,但 OUTER 代表的就是外部行。LEFT OUTER JOIN 把左表记为保留表,RIGHT OUTER JOIN 把右表记为保留表,FULL OUTER JOIN 把左右表都记为保留表。添加外部行的工作就是在 VT2 表的基础上添加保留表中被过滤条件过滤掉的数据,非保留表中的数据被赋予 NULL 值,最后生成虚拟表 VT3

  4. 应用 WHERE 过滤器

    对上一步骤产生的虚拟表 VT3 进行 WHERE 条件过滤,只有符合<where_condition>的记录才会输出到虚拟表 VT4 中

    在当前应用 WHERE 过滤器时,有两种过滤是不被允许的:

    • 由于数据还没有分组,因此现在还不能在 WHERE 过滤器中使用 where_condition=MIN(col)这类对统计的过滤
    • 由于没有进行列的选取操作,因此在 SELECT 中使用列的别名也是不被允许的,如 SELECT city as c from students WHERE c = '天津' 是不允许出现的
  5. 分组

    在本步骤中根据指定的列对上个步骤中产生的虚拟表进行分组,最后得到虚拟表 VT5

  6. 应用 HAVING 过滤器

    在该步骤中对于上一步产生的虚拟表应用 HAVING 过滤器,HAVING 是对分组条件进行过滤的筛选器。生成虚拟表VT6。

  7. 处理 SELECT 列表

    在这一步中,将 SELECT 中指定的列从上一步产生的虚拟表中选出生成虚拟表 VT7。

  8. 应用 ORDER BY 字句

    根据 ORDER BY 子句中指定的列对上一步输出的虚拟表进行排列,返回新的虚拟表 VT8。

    注意:在 MySQL 数据库中,NULL 值在升序过程中总是首先被选出,即 NULL 值在 ORDER BY 子句中被视为最小值

  9. LIMIT 子句

    在该步骤中应用 LIMIT 子句,从上一步骤的虚拟表中选出从指定位置开始的指定行数据。对于没有应用 ORDER BY 的 LIMIT 子句,结果同样可能是无序的,因此 LIMIT 子句通常和 ORDER BY 子句一起使用。

四、注意

上面所讨论的顺序皆为理论上的执行顺序,实际上数据库引擎并不是通过连接、过滤和分组来运行查询,因为它实现了一系列优化来提升查询速度(不影响最终的返回结果)。数据库引擎可能会为了提高查询的速度把一些过滤条件进行提前,当然前提是不会对返回的结果造成影响。

SELECT
	ss.student_id,sum(se.grade) as total,ss.city
FROM
	students ss
	LEFT JOIN score se ON ss.student_id = se.student_id 
WHERE
	ss.city = "天津"

这个 sql 学生城市是天津的只有三个,如果在学生很多的情况下如果先做城市的筛选后再对两张表做笛卡尔积可以很大程度的提升性能,并且也不会对返回的结果造成影响。这时实际上SQL的执行顺序可能就与理论上的执行顺序不一样了。

参考资料

  1. SQL queries don't start with SELECT

本文原创,才疏学浅,如有纰漏,欢迎指正。尊贵的朋友,如果本文对您有所帮助,欢迎点赞,并期待您的反馈,以便于不断优化。

原文地址: https://www.emanjusaka.top/2023/09/sql-query-order

微信公众号:emanjusaka的编程栈文章来源地址https://www.toymoban.com/news/detail-693341.html

到了这里,关于SQL 查询的执行顺序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 二、SQL-5.DQL-9).执行顺序

    先执行①from(定义emp的别名为e),再执行②where(调用别名e):  再执行④select:  给④select取别名ename,eage,此时把②where别名e.age改为eage: 报错,②where在④select之前执行,eage还没有定义   ④select在⑤order by之前执行,所有order by可以用select中定义的别名:

    2024年02月15日
    浏览(38)
  • sql顺序倒序查询

    要根据 orderNum 字段的顺序查询,你可以使用 SQL 的 ORDER BY 子句。默认情况下, ORDER BY 是按升序排序的,但你可以使用 DESC 来指定降序排序。 以下是一个示例查询,按照 orderNum 字段的顺序将结果返回: 如果你想按降序(倒序)排序,可以使用 DESC : 请将 your_

    2024年02月05日
    浏览(55)
  • 数据库--SQL关键字的执行顺序

    数据库-- 数据类型 : http://t.csdn.cn/RtqMD 数据库-- 三大范式、多表查询、函数sql: http://t.csdn.cn/udJSG 数据库-- MySQL增删改查: http://t.csdn.cn/xkiti select   from   join   where   group by   having   order by   聚合函数   limit   top  以及逻辑运算符not  and    or    一: 语法顺序    

    2024年02月12日
    浏览(51)
  • 基本 SQL 命令 、重要的 SQL命令、SQL 约束 及 SQL语句 的 执行顺序

    学习目标如下: SQL语句执行顺序 基本 SQL 命令:` FROM ON JOIN WHERE GROUP BY AGG_FUNC WITH HAVING SELECT 从数据库中提取数据 UNION DISTINCT ORDER BY 排序 LIMIT 重要的sql命令: 1、SELECT - 从数据库中提取数据 2、UPDATE - 更新数据库中的数据 3、DELETE - 从数据库中删除数据 4、INSERT INTO - 向数据库

    2024年02月08日
    浏览(45)
  • SQL ASNI where from group order 顺序 where和having,SQL底层执行原理

    SQL语句执行顺序: from–where–group by --having — select -- order 第一步:from语句,选择要操作的表。 第二步:where语句,在from后的表中设置筛选条件,筛选出符合条件的记录。 第三步:group by语句,把筛选出的记录进行分组。 第四步:having语句,设置条件筛选分组后的数据。

    2024年02月14日
    浏览(54)
  • oracle sql执行耗时查询

    1,使用SQL Trace SQL Trace 是 Oracle 提供的一种跟踪 SQL 语句执行的工具,通过该工具我们可以获取到 SQL 语句的详细执行过程信息,包括执行时间、执行计划、IO 等。使用 SQL Trace 的方法是: ALTER SESSION SET SQL_TRACE = TRUE; 该语句执行后,会在用户的 Trace 目录下生成一个与该会话相关

    2024年02月04日
    浏览(33)
  • SQL Server查询历史执行记录

    1. 使用 SQL Server Management Studio (SSMS) 的查询执行记录功能: 打开 SSMS,连接到要查看执行记录的数据库服务器。 在“对象资源管理器”窗格中,右键单击要查看执行记录的数据库,然后选择“报表” “标准报表” “执行记录”。 在“执行记录”窗口中,选择要查看的时间范

    2024年02月17日
    浏览(41)
  • GaussDB SQL查询语句执行过程解析

    本文分享自华为云社区《【GaussTech第2期】GaussDB SQL查询语句执行过程解析》,作者: GaussDB 数据库。 SQL于关系型数据库而言,重要性不言而喻。就像一个乐团的指挥,指导着作品的正确演绎和节奏的和谐统一。华为云GaussDB作为新一代关系型分布式数据库,具备卓越的技术性

    2024年04月24日
    浏览(47)
  • 01 | 一条 SQL 查询语句是如何执行的?

    以下内容出自 《MySQL 实战 45 讲》 一条 SQL 查询语句是如何执行的? 下面是 MySQL 的基本架构示意图,从中可以清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程。 大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。 Server 层包括连接器、查询缓存、分析器、优化器

    2024年02月10日
    浏览(46)
  • 【MySQL系列】- Select查询SQL执行过程详解

    一条SQL语句从发送到数据并返回结果,主要经历以下几个过程: 连接器 : 查询缓存 :如果开启了查询缓存,则会经过这一步,但是大多数情况下都不是开启的,也不建议开启;MySQL8.0之后也删除了这一块功能。 分析器 : 优化器 执行器 2.1. 连接器 如果想对MySQL进行操作,第

    2024年02月08日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包