SQL 查询语句总是先执行 SELECT?你们都错了
很多 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 table
GROUP BY full_name
从这个语句来看,好像 GROUP BY 是在 SELECT 之后执行的,因为它引用了 SELECT 中的一个别名。但实际上不一定要这样,数据库引擎可以把查询重写成这样:
SELECT CONCAT(first_name, ' ', last_name) AS full_name, count(*)
FROM table
GROUP BY CONCAT(first_name, ' ', last_name)
这样 GROUP BY 仍然先执行。
数据库引擎还会做一系列检查,确保 SELECT 和 GROUP BY 中的东西是有效的,所以会在生成执行计划之前对查询做一次整体检查。
数据库可能不按顺序执行查询(优化)
在实际当中,数据库不一定会按照 JOIN、WHERE、GROUP BY 的顺序来执行查询,因为它们会进行一系列优化,把执行顺序打乱,从而让查询执行得更快,只要不改变查询结果。
这个查询说明了为什么需要以不同的顺序执行查询:
SELECT * FROM
owners LEFT JOIN cats ON owners.id = cats.owner
WHERE 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) # JOIN
df = df[df.created_at > 1000] # WHERE
df = df.groupby('something', num_yes = ('yes', 'sum')) # GROUP BY
df = df[df.num_yes > 2] # HAVING, 对 GROUP BY 结果进行过滤
df = df[['num_yes', 'something1', 'something']] # SELECT, 选择要显示的列
df.sort_values('sometthing', ascending=True)[:30] # ORDER BY 和 LIMIT
df[:30]
这样写并不是因为 pandas 规定了这些规则,而是按照 JOIN/WHERE/GROUP BY/HAVING 这样的顺序来写代码会更有意义些。不过我经常会先写 WHERE 来改进性能,而且我想大多数数据库引擎也会这么做。
R 语言里的 dplyr 也允许开发人员使用不同的语法编写 SQL 查询语句,用来查询 Postgre、MySQL 和 SQLite。
SQL 查询语句总是先执行 SELECT?你们都错了的更多相关文章
- mysql数据库系统学习(一)---一条SQL查询语句是如何执行的?
本文基于----MySQL实战45讲(极客时间----林晓斌 )整理----->https://time.geekbang.org/column/article/68319 一.第一节:一条sq ...
- 一文读懂一条 SQL 查询语句是如何执行的
2001 年 MySQL 发布 3.23 版本,自此便开始获得广泛应用,随着不断地升级迭代,至今 MySQL 已经走过了 20 个年头. 为了充分发挥 MySQL 的性能并顺利地使用,就必须正确理解其 ...
- 01.基础架构:一条SQL查询语句是如何执行的?学习记录
01.基础架构:一条SQL查询语句是如何执行的?学习记录http://naotu.baidu.com/file/1c8fb5a0f2497c3a2655fed89099cb96?token=ff25d ...
- mysql实战45讲读书笔记(一) 一条SQL查询语句是如何执行的
我们经常说,看一个事儿千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题.同样,对于MySQL的学习也是这样.平时我们使用数据库,看到的通常都是一个整体.比如,你有个最简单的表 ...
- 01 | 基础架构:一条SQL查询语句是如何执行的?
这是专栏的第一篇文章,我想来跟你聊聊MySQL的基础架构.我们经常说,看一个事儿千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题.同样,对于MySQL的学习也是这样.平时我们 ...
- 一条SQL查询语句是如何执行的?
本篇文章将通过一条 SQL 的执行过程来介绍 MySQL 的基础架构. 首先有一个 user_info 表,表里有一个 id 字段,执行下面这条查询语句: select * from user_inf ...
- 基础架构:一条SQL查询语句是如何执行的?
https://time.geekbang.org/column/article/68319?code=pEYaxHnjO23LQHW4CJgL706EXlpAJnbOOiT2y42cWwU%3D 这 ...
- MySQL数据库详解(一)执行SQL查询语句时,其底层到底经历了什么?
一条SQL查询语句是如何执行的? 前言 大家好,我是WZY,今天我们学习下MySQL的基础框架,看一件事千万不要直接陷入细节里,你应该先鸟瞰其全貌,这样能够帮助你从高维度理解问题.同样,对于MyS ...
- 一条SQL更新语句是如何执行的
文章首发于公众号「蝉沐风」,认真写好每一篇文章,欢迎大家关注交流 这是图解MySQL的第2篇文章,这篇文章会通过一条SQL更新语句的执行流程让大家清楚地明白: 什么是InnoDB页?缓存页又是什么?为 ...
随机推荐
- thymeleaf-extras-springsecurity在Spring或SpringBoot中html页面命名空间
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
- Log4j讲解
讲解 通常,我们写代码的过程中,免不了要输出各种调试信息.在没有使用任何日志工具之前,都会使用 System.out.println 来做到. 这么做直观有效,但是有一系列的缺点:1. 不知道这句话是 ...
- tp 创建文件并写入数据
代码:1.$url = Env::get('root_path').'application/admin/test.txt'; //定义创建路径 $file = fopen($url,"w& ...
- postman Variables变量的详解与应用
变量 变量类型(按照作用域划分) 全局变量(全局环境里面的变量) 集合变量(请求集合里声明的变量) 自定义环境变量 数据变量(在runner时文件变量) 本地变量 变量权重类型 全局变量 < 集 ...
- KMP(The Knuth-Morris-Pratt Algorithm)
本文代码来自于中国大学MOOC KMP课件下载 注释内容为自己理解,如有错误请评论,或者私信给我,谢谢 #include <stdio.h> #include "stdlib.h ...
- [刷题] PTA 03-树1 树的同构
程序: 1 #include <stdio.h> 2 #define MaxTree 10 3 #define ElementType char 4 #define Tree int 5 ...
- coverage report
转载:http://blog.sina.cn/dpool/blog/s/blog_7853c3910102yn77.html VCS仿真可以分成两步法或三步法, 对Mix language, 必须用三 ...
- linux中级之ansible配置(roles)
一.roles介绍 什么情况下用到roles? 假如我们现在有3个被管理主机,第一个要配置成httpd,第二个要配置成php服务器,第三个要配置成MySQL服务器.我们如何来定义playbook? 第 ...
- RSA算法在Python Django中的简单应用
说明 RSA算法是当今使用最广泛,安全度最高的加密算法. • RSA算法的安全性理论基础 [引]根据百科介绍,对极大整数做因数分解的难度决定了RSA算法的可靠性.换言之,对一极大整数做因数分解愈困难, ...
- python 中的变量内存以及关于is ==、 堆栈、
在工作学习中会碰到一些python中变量与内存层面的问题理解,虽然是在不断的解决,但是并没有做过这方面的总结. 变量:用来标识(identify)一块内存区域.为了方便表示内存,我们操作变量实质上是在 ...