点击上方“朱小厮的博客”,选择“设为星标”

后台回复”1024“领取惊喜资料

很多 SQL 查询都是以 SELECT 开始的。不过,最近我跟别人解释什么是窗口函数,我在网上搜索”是否可以对窗口函数返回的结果进行过滤“这个问题,得出的结论是”窗口函数必须在 WHERE 和 GROUP BY 之后,所以不能”。于是我又想到了另一个问题:SQL 查询的执行顺序是怎样的?

好像这个问题应该很好回答,毕竟自己已经写了上万个 SQL 查询了,有一些还很复杂。但事实是,我仍然很难确切地说出它的顺序是怎样的。

SQL 查询的执行顺序

于是我研究了一下,发现顺序大概是这样的。SELECT 并不是最先执行的,而是在第五个。

这张图回答了以下这些问题

这张图与 SQL 查询的语义有关,让你知道一个查询会返回什么,并回答了以下这些问题:

  • 可以在 GRROUP BY 之后使用 WHERE 吗?(不行,WHERE 是在 GROUP BY 之后!)

  • 可以对窗口函数返回的结果进行过滤吗?(不行,窗口函数是 SELECT 语句里,而 SELECT 是在 WHERE 和 GROUP BY 之后)

  • 可以基于 GROUP BY 里的东西进行 ORDER BY 吗?(可以,ORDER BY 基本上是在最后执行的,所以可以基于任何东西进行 ORDER BY)

  • LIMIT 是在什么时候执行?(在最后!)

但数据库引擎并不一定严格按照这个顺序执行 SQL 查询,因为为了更快地执行查询,它们会做出一些优化,这些问题会在以后的文章中解释。

所以:

  • 如果你想要知道一个查询语句是否合法,或者想要知道一个查询语句会返回什么,可以参考这张图;

  • 在涉及查询性能或者与索引有关的东西时,这张图就不适用了。

混合因素:列别名

有很多 SQL 实现允许你使用这样的语法:

SELECT CONCAT(first_name, \' \', last_name) AS full_name, count(*)FROM tableGROUP BY full_name

从这个语句来看,好像 GROUP BY 是在 SELECT 之后执行的,因为它引用了 SELECT 中的一个别名。但实际上不一定要这样,数据库引擎可以把查询重写成这样:

SELECT CONCAT(first_name, \' \', last_name) AS full_name, count(*)FROM tableGROUP BY CONCAT(first_name, \' \', last_name)

这样 GROUP BY 仍然先执行。

数据库引擎还会做一系列检查,确保 SELECT 和 GROUP BY 中的东西是有效的,所以会在生成执行计划之前对查询做一次整体检查。

数据库可能不按照这个顺序执行查询(优化)

在实际当中,数据库不一定会按照 JOIN、WHERE、GROUP BY 的顺序来执行查询,因为它们会进行一系列优化,把执行顺序打乱,从而让查询执行得更快,只要不改变查询结果。

这个查询说明了为什么需要以不同的顺序执行查询:

SELECT * FROMowners LEFT JOIN cats ON owners.id = cats.ownerWHERE cats.name = \'mr darcy\'

如果只需要找出名字叫“mr darcy”的猫,那就没必要对两张表的所有数据执行左连接,在连接之前先进行过滤,这样查询会快得多,而且对于这个查询来说,先执行过滤并不会改变查询结果。

数据库引擎还会做出其他很多优化,按照不同的顺序执行查询,不过我并不是这方面的专家,所以这里就不多说了。

LINQ 的查询以 FROM 开头

LINQ(C#和 VB.NET 中的查询语法)是按照 FROM…WHERE…SELECT 的顺序来的。这里有一个 LINQ 查询例子:

var teenAgerStudent = from s in studentList                      where s.Age > 12 && s.Age < 20                      select s;

pandas 中的查询也基本上是这样的,不过你不一定要按照这个顺序。我通常会像下面这样写 pandas 代码:

df = thing1.join(thing2)      # JOINdf = df[df.created_at > 1000] # WHEREdf = df.groupby(\'something\', num_yes = (\'yes\', \'sum\')) # GROUP BYdf = df[df.num_yes > 2]       # HAVING, 对 GROUP BY 结果进行过滤df = df[[\'num_yes\', \'something1\', \'something\']] # SELECT, 选择要显示的列df.sort_values(\'sometthing\', ascending=True)[:30] # ORDER BY 和 LIMITdf[:30]

这样写并不是因为 pandas 规定了这些规则,而是按照 JOIN/WHERE/GROUP BY/HAVING 这样的顺序来写代码会更有意义些。不过我经常会先写 WHERE 来改进性能,而且我想大多数数据库引擎也会这么做。

R 语言里的 dplyr 也允许开发人员使用不同的语法编写 SQL 查询语句,用来查询 Postgre、MySQL 和 SQLite。

想知道更多?描下面的二维码关注我

【限时推广1】

极客时间专属优惠码:SIDANIUBI,使用这个优惠码购买极客时间的任何一门课程都可以减20元,这是双11的活动,优惠码有效期至11.15,认准 SIDANIUBI

【限时推广2】

阿里云 新人专属福利,服务器1折起,最低低至86元,拼团地址:http://suo.im/59kDxw,如有需要,直接扫码也可以参与拼团。

朕已阅 

SQL 查询语句总是先执行 SELECT?相关推荐

  1. SQL查询语句总是先执行SELECT?你们都错了。。。

    来源 | infoq.cn/article/Oke8hgilga3PTZ3gWvbg 很多 SQL 查询都是以 SELECT 开始的.不过,最近我跟别人解释什么是窗口函数,我在网上搜索"是否 ...

  2. SQL 查询语句总是先执行 SELECT?你们都错了

    很多 SQL 查询都是以 SELECT 开始的.不过,最近我跟别人解释什么是窗口函数,我在网上搜索"是否可以对窗口函数返回的结果进行过滤"这个问题,得出的结论是"窗口函数 ...

  3. 怎么做mysql查询系统_mysql数据库系统学习(一)---一条SQL查询语句是如何执行的?...

    一.第一节:一条sql查询语句是怎样执行的 5.5.5版本以后,默认使用存储引擎为InnoDB 不使用查询缓存,MySQL8.0没有查询缓存这个功能 总体来说:MySQL分为service层和存储引擎 ...

  4. 【mysql技术内幕1】mysql基础架构-一条SQL查询语句是如何执行的

    文章目录 1 一条SQL查询语句是如何执行的 2 mysql体系结构 3 InnoDB存储引擎 4 总结 1 一条SQL查询语句是如何执行的 ​ 通常我们使用数据库,都是将数据库看成一个整体,我们的应 ...

  5. 听说你写sql很溜,一条sql查询语句是如何执行的?

    我们项目中必不可少要与数据库接触,那么一条sql查询语句是如何执行的呢? 本文以MySQL数据库为例.MySQL是典型的C/S架构(client客户端/server服务端),客户端进程向服务端进程发送 ...

  6. MySQL番外篇:一条SQL查询语句是如何执行的?

    在面试的过程中,有的面试官会给出一条简单的SQL查询语句,让简单说一下执行的过程. SELECT * FROM emp where age=30; 以下问MySQL的基本架构图,从中可以看出SQL语句 ...

  7. .net函数查询_SQL查询语句总是先执行SELECT?你们都错了!

    很多 SQL 查询都是以 SELECT 开始的.不过,最近我跟别人解释什么是窗口函数,我在网上搜索"是否可以对窗口函数返回的结果进行过滤"这个问题,得出的结论是"窗口函数 ...

  8. sqlserver 查询某个时间段执行sql语句_为什么 SQL 查询不是先执行SELECT语句?

    作者:Julia Evans    译者:无明    链接:infoq.cn/article/Oke8hgilga3PTZ3gWvbg 很多 SQL 查询都是以 SELECT 开始的.不过,最近我跟别 ...

  9. .sql文件如何执行_深入理解SQL原理:SQL查询语句是如何执行的?

    本篇文章将通过一条 SQL 的执行过程来介绍 MySQL 的基础架构. 首先有一个 user_info 表,表里有一个 id 字段,执行下面这条查询语句: select * from user_inf ...

最新文章

  1. 为什么Kubernetes的存储如此艰难?
  2. Python使用matplotlib函数subplot可视化多个不同颜色的折线图、为指定的子图添加图例信息(legend)
  3. ListModel QML类型
  4. linux中tar命令的使用
  5. Java中map关于putAll()和“=”的区别
  6. 【Node学习】—Express框架的安装
  7. 五种常用web服务器jvm参数设置
  8. sublime3 配置go的开发环境
  9. 联合国应考虑建设第二总部
  10. vue中数组按照下标移除其中一个_JDK 中的栈竟然是这样实现的?
  11. Matlab Coder将m文件转换成C/C++
  12. php利用curl实现多进程下载文件类
  13. 阿里云对象存储OSS及CDN加速配置
  14. FFmpeg 加水印 加马赛克
  15. java水果忍者7723_水果忍者之天下第一
  16. WiFi 802.11可调参数说明---电源管理调整(聆听间隔/DTIM/ATIM)
  17. c语言头结点存放元素,【笔记】带头节点的单链表的C语言实现
  18. 工资12000扣多少税?--2020年个人所得税最新算法Excel表格
  19. 计算机二级怎么样分屏方便,全国计算机等级考试二级教程
  20. 小升初 择校简历标准

热门文章

  1. ReentrantLock源码
  2. android datepicker使用方法,android中DatePicker和TimePicker的使用方法详解
  3. python爬虫贴吧_Python爬虫如何爬取贴吧内容
  4. KDE Applications 19.04 发布,包含大量更新
  5. Unity3D如何有效地组织代码?(转)
  6. 低门槛彻底理解JavaScript中的深拷贝和浅拷贝
  7. DataGrid 功能实现收集(一)
  8. 常用的web安全处理
  9. ubuntu 下 安装 配置 jdk1.7 (tar.gz)
  10. SyntaxError: Missing parentheses in call to 'print'