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页?缓存页又是什么?为 ...
随机推荐
- Xshell、Xftp评估过期的解决办法
介绍一个 FTP客户端-IIS7服务器管理工具作为FTP客户端,它支持批量管理ftp站点.定时上传和定时下载,定时备份,且操作简洁.同时iis7服务器管理工具还是vnc客户端.并且支持批量管理 ...
- 使用TK框架中updateByPrimaryKey与updateByPrimaryKeySelective区别
int updateByPrimaryKey(T var1); int updateByPrimaryKeySelective(T var1); updateByPrimaryKeySelective ...
- 逆向工程初步160个crackme-------6
工具:1. 按钮事件地址转换器E2A 2. PEID 3. Ollydbg 同样我们先来运行一下这个程序, ok按钮是被禁用的,有一个help按钮点击后弹出一个消息框:消息框显示提示信息为.本程序需要 ...
- easy-flows源码研习
一.项目概述 1.原项目github地址:https://github.com/j-easy/easy-flows.git 2.easy-flows可以用非常简易的api创建常用的可组合的工作流.涵盖 ...
- IOC随笔小记录
对IOC的一点学习笔记 IOC (Inversion of Control):控制反转 DI (Dependency Injection):依赖注入 1.在没有使用IOC的情况下是如何进行的 在Use ...
- BUAA OS实验调试指南:从看懂到看开
一般的调试流程其实很简单:发现问题,稳定复现,确定临界条件,定位问题,修复问题,核查结果.迭代这个过程,形成一个闭环 老实说,OS的实验代码,开箱体验极差,程序跳来跳去,进了Lab4后还要考虑内核态切 ...
- 『动善时』JMeter基础 — 22、JMeter中实现参数化(CSV)
目录 1.参数化的定义 2.什么情况下需要用到参数化 3.JMeter实现参数化的方式 4.CSV数据文件设置界面详细说明 (1)CSV数据文件设置组件界面说明 (2)补充说明:Recycle on ...
- [bug] IDEA编译时出现 Information:java: javacTask: 源发行版 1.8 需要目标发行版 1.8
原因 jdk版本选低了 解决 将以下几处jdk版本修改为1.8 Project Structure(File->Project Structure...)>Sources>Langu ...
- [Java] Git
版本控制 VCS(Version Control System):版本控制系统 主要功能:版本控制.主动提交.中央仓库 中央仓库功能:保存版本历史.同步团队代码 DVCS(Distributed VC ...
- S3待机 S4休眠
https://hceng.cn/2018/01/18/Linux%E7%94%B5%E6%BA%90%E7%AE%A1%E7%90%86/ 1.1系统睡眠模型Suspend On (on) S0 - ...