

SQL 查询语句总是先执行 SELECT?你们都错了
source link: https://www.tuicool.com/articles/Ev2Ijq3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者 | Julia Evans
译者 | 无明
很多 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。
原文链接:
https://jvns.ca/blog/2019/10/03/sql-queries-don-t-start-with-select/
活动推荐
SQL 的性能问题一直是影响到金融系统用户体验甚至是系统可用率的关键因素。陆金所的解决方案为:基于陆金所数年的 SQLmap 代码、执行计划、生产运行监控信息、DBA review建议等数据结合 AI 算法训练和优化 AI SQLreview 系统。具体成效如何呢?推荐大家到ArchSummit全球架构师峰会(北京站)听听王英杰老师怎么说~
8折购票 倒计时 ,限时立减 1760元 , 团购 更便宜哦~了解详情请联系票务经理灰灰:15600537884 (同微信)。
Recommend
-
57
Go 的select语句是一种仅能用于channl发送和接收消息的专用语句,此语句运行期间是阻塞的;当select中没有case语句的时候,会阻塞当前的groutine。所以,有人也会说select是用来阻塞监听goroutine的。 还有人说:select是Golang在语言层面...
-
55
Go 的select语句是一种仅能用于channl发送和接收消息的专用语句,此语句运行期间是阻塞的;当select中没有case语句的时候,会阻塞当前的groutine。所以,有人也会说select是用来阻塞监听goroutine的。 还有人说:select是Golang...
-
15
长按扫描上方二维码了解
-
3
原来一条select语句在MySQL是这样执行的《死磕MySQL系列 一》 一生挚友redo log、binlog...
-
4
在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有没有使用上了索引,有没有做全表扫描,这都可以通过explain命令来查看...
-
1
常规语句应用基础 原创 1、for循环语句range()函数包含3个参数,其函数原型为range(start, stop, step)start:计数从st...
-
8
TL;NRs 根据实测结果,MySQL8.0.28 中 SQL 语句的执行顺序为: (8) SELECT (5) DISTINCT <select_list> (1) FROM <left_table> (3) <join_type> JOIN <right_table> (4) ON <jo...
-
8
1.问题背景前段时间,一个业务线的小伙伴大G找过来,如下是我俩的对话。大G:云杰,听说你MySQL挺厉害的,我最近遇到一个奇怪问题,不知道你遇到过没,请教你下。我:请教不敢当,我也就是个MySQL入门级选手,说来看...
-
7
MySQL基础架构:SQL查询语句执行过程 作者:测试开发小记 2022-09-01 16:42:47 MySQL是一种关系型数据库管理系统,采用的是分层结构,本文中将简单介绍MySQL数据库的内部架构。
-
5
MySQL中明确查询语句的执行顺序极其重要,了解执行顺序才不至于犯一些简单错误,例如having 后面是否可以使用 select 中重命名的列名等问题。另外SQL中实际使用最频繁的就是查询(Queing),要想写出高质量、高性能的查询语句,必须深入地了解SQL的逻辑查询处理顺序和...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK