mysql-4:SQL的解析顺序
SQL语句的解析顺序
文章目录
- SQL语句的解析顺序
- 编写顺序与解析顺序
- 解析顺序关键字
- FROM
- ON
- OUTER JOIN
- WHERE
- GROUP BY
- HAVING
- SELECT
- DISTINCT
- ORDER BY
- LIMIT
- 解析流程
- 流程分析
- 流程说明
- WHERE条件解析顺序
编写顺序与解析顺序
- 编写顺序
SELECT DISTINCT
< select_list >
FROM
< left_table > < join_type >
JOIN < right_table > ON < join_condition >
WHERE
< where_condition >
GROUP BY
< group_by_list >
HAVING
< having_condition >
ORDER BY
< order_by_condition >
LIMIT < limit_number >
- 解析顺序
-- 行过滤
1 FROM <left_table>
2 ON <join_condition>
3 <join_type> JOIN <right_table> 第二步和第三步会循环执行
4 WHERE <where_condition> 第四步会循环执行,多个条件的执行顺序是从左往右的。
5 GROUP BY <group_by_list>
6 HAVING <having_condition>
--列过滤
7 SELECT 分组之后才会执行SELECT
8 DISTINCT <select_list>
--排序
9 ORDER BY <order_by_condition>
-- MySQL附加
10 LIMIT <limit_number> 前9步都是SQL92标准语法。limit是MySQL的独有语法。
解析顺序关键字
FROM
- 对FROM的左边的表和右边的表计算 笛卡尔积(CROSS JOIN) 。产生虚表VT1:
mysql> select * from product,category;
+-----+-----------------+-------+-------+------+----+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+-----------------+-------+-------+------+----+--------------+
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 2 | 国内食品 |
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 3 | 国内服装 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 2 | 国内食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 3 | 国内服装 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 3 | 国内服装 |
| 4 | 十三香 | 10 | NULL | 2 | 1 | 国外食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 3 | 国内服装 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 1 | 国外食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 3 | 国内服装 |
| 6 | 泰国大枣 | 98 | NULL | 20 | 1 | 国外食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | 2 | 国内食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | 3 | 国内服装 |
| 7 | iPhone手机 | 800 | NULL | 30 | 1 | 国外食品 |
| 7 | iPhone手机 | 800 | NULL | 30 | 2 | 国内食品 |
| 7 | iPhone手机 | 800 | NULL | 30 | 3 | 国内服装 |
+-----+-----------------+-------+-------+------+----+--------------+
21 rows in set (0.00 sec)
通过在 FROM 子句中列出多个表格,你可以执行一个叫做交叉连接(Cross Join)的操作,它会将product,category两个表的每一行进行组合,生成一个包含所有可能组合的结果集。
ON
- 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中:
mysql> select * from product a, category b where a.cid=b.id;
+-----+-----------------+-------+-------+------+----+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+-----------------+-------+-------+------+----+--------------+
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
+-----+-----------------+-------+-------+------+----+--------------+
5 rows in set (0.00 sec)
OUTER JOIN
- 如果指定了 OUTER JOIN(比如left join、 right join) ,那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2 中,产生虚拟表VT3
- 如果FROM子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止
- 以左表数据为准
mysql> select * from product a left outer join category b on a.cid=b.id;
+-----+-----------------+-------+-------+------+------+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+-----------------+-------+-------+------+------+--------------+
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | NULL | NULL |
| 7 | iPhone手机 | 800 | NULL | 30 | NULL | NULL |
+-----+-----------------+-------+-------+------+------+--------------+
7 rows in set (0.00 sec)
- 以右表数据为准
mysql> select * from product a right outer join category b on a.cid=b.id;
+------+-----------------+-------+-------+------+----+--------------+
| pid | pname | price | pdate | cid | id | cname |
+------+-----------------+-------+-------+------+----+--------------+
| 1 | 泰国大榴莲 | 98 | NULL | 1 | 1 | 国外食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 3 | 新疆切糕 | 68 | NULL | 2 | 2 | 国内食品 |
| 4 | 十三香 | 10 | NULL | 2 | 2 | 国内食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| NULL | NULL | NULL | NULL | NULL | 3 | 国内服装 |
+------+-----------------+-------+-------+------+----+--------------+
6 rows in set (0.00 sec)
WHERE
- 对虚拟表VT3 进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4 中
此时因为分组,不能使用聚合运算;也不能使用SELECT中创建的别名;
- 与ON的区别
- 如果有外部列,ON针对过滤的是关联表,主表(保留表)会返回所有的列;
- 如果没有添加外部列,两者的效果是一样的;
- 应用
- 对主表的过滤应该放在WHERE;
- 对于关联表,先条件查询后连接则用ON,先连接后条件查询则用WHERE;
mysql> select * from product a left outer join category b on a.cid=b.id where
a.pname='泰国大枣';
+-----+--------------+-------+-------+------+------+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+--------------+-------+-------+------+------+--------------+
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | NULL | NULL |
+-----+--------------+-------+-------+------+------+--------------+
3 rows in set (0.00 sec)
GROUP BY
- 根据group by子句中的列,对VT4中的记录进行分组操作,产生虚拟表VT5。
注意:其后处理过程的语句,如SELECT,HAVING,所用到的列必须包含在GROUP BY中。对于没有出现的,得用聚合函数;
- 原因:
- GROUP BY改变了对表的引用,将其转换为新的引用方式,能够对其进行下一级逻辑操作的列会减少;
- 理解
- 根据分组字段,将具有相同分组字段的记录归并成一条记录,因为每一个分组只能返回一条记录,除非是被过滤掉了,而不在分组字段里面的字段可能会有多个值,多个值是无法放进一条记录的,所以必须通过聚合函数将这些具有多值的列转换成单值;
mysql> select * from product a left outer join category b on a.cid=b.id where
a.pname='泰国大枣' group by a.price;
+-----+--------------+-------+-------+------+------+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+--------------+-------+-------+------+------+--------------+
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 6 | 泰国大枣 | 98 | NULL | 20 | NULL | NULL |
+-----+--------------+-------+-------+------+------+--------------+
3 rows in set (0.01 sec)
HAVING
- 对虚拟表VT5 应用having过滤,只有符合的记录才会被插入到虚拟表VT6 中。
mysql> select * from product a left outer join category b on a.cid=b.id where
a.pname='泰国大枣' group by a.price having b.id <=2;
+-----+--------------+-------+-------+------+------+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+--------------+-------+-------+------+------+--------------+
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
+-----+--------------+-------+-------+------+------+--------------+
2 rows in set (0.00 sec)
SELECT
- 这个子句对SELECT子句中的元素进行处理,生成VT5表。
- (5-J1)计算表达式计算SELECT 子句中的表达式,生成VT5-J1
DISTINCT
- 寻找VT5-1中的重复列,并删掉,生成VT5-J2
- 如果在查询中指定了DISTINCT子句,则会创建一张内存临时表(如果内存放不下,就需要存放在硬盘了)。这张临时表的表结构和上一步产生的虚拟表VT5是一样的,不同的是对进行DISTINCT操作的列增
加了一个唯一索引,以此来除重复数据。
mysql> select distinct a.pname from product a left outer join category b on
a.cid=b.id where a.pname='泰国大枣' group by a.price ;
+--------------+
| pname |
+--------------+
| 泰国大枣 |
+--------------+
1 row in set (0.00 sec)
ORDER BY
- 从 VT5-J2 中的表中,根据ORDER BY 子句的条件对结果进行排序,生成VT6表
唯一可使用SELECT中别名的地方
mysql> select * from product a left outer join category b on a.cid=b.id where
a.pname='泰国大枣' group by a.price having b.id <=2 order by b.id;
+-----+--------------+-------+-------+------+------+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+--------------+-------+-------+------+------+--------------+
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
| 5 | 泰国大枣 | 20 | NULL | 2 | 2 | 国内食品 |
+-----+--------------+-------+-------+------+------+--------------+
2 rows in set (0.00 sec)
LIMIT
- LIMIT子句从上一步得到的 VT6虚拟表 中选出从指定位置开始的指定行数据
MySQL特有
offset 和 rows 的正负带来的影响;
- 当偏移量很大时效率是很低的,可以这么做:
- 采用子查询的方式优化 ,在子查询里先从索引获取到最大id,然后倒序排,再取N行结果集
- 采用INNER JOIN优化 ,JOIN子句里也优先从索引获取ID列表,然后直接关联查询获得最终结果
mysql> select * from product a left outer join category b on a.cid=b.id where
a.pname='泰国大枣' group by a.price having b.id <=2 order by b.id limit 1;
+-----+--------------+-------+-------+------+-
-----+--------------+
| pid | pname | price | pdate | cid | id | cname |
+-----+--------------+-------+-------+------+------+--------------+
| 2 | 泰国大枣 | 38 | NULL | 1 | 1 | 国外食品 |
+-----+--------------+-------+-------+------+------+--------------+
1 row in set (0.00 sec)
解析流程

流程分析
-
- FROM(将最近的两张表,进行笛卡尔积)—VT1
-
- ON(将VT1按照它的条件进行过滤)—VT2
-
- LEFT JOIN(保留左表的记录)—VT3
-
- WHERE(过滤VT3中的记录)–VT4…VTn
-
- GROUP BY(对VT4的记录进行分组)—VT5
-
- HAVING(对VT5中的记录进行过滤)—VT6
-
- SELECT(对VT6中的记录,选取指定的列)–VT7
-
- ORDER BY(对VT7的记录进行排序)–VT8
-
- LIMIT(对排序之后的值进行分页)–MySQL特有的语法
流程说明
- 单表查询:根据 WHERE 条件过滤表中的记录,形成中间表(这个中间表对用户是不可见的);然后根据 SELECT 的选择列选择相应的列进行返回最终结果。
- 两表连接查询:对两表求积(笛卡尔积)并用 ON 条件和连接类型进行过滤形成中间表;然后根据WHERE条件过滤中间表的记录,并根据 SELECT 指定的列返回查询结果。
笛卡尔积:行相乘、列相加。
- 多表连接查询:先对第一个和第二个表按照两表连接做查询,然后用查询结果和第三个表做连接查询,以此类推,直到所有的表都连接上为止,最终形成一个中间的结果表,然后根据WHERE条件过滤中间表的记录,并根据SELECT指定的列返回查询结果。
WHERE条件解析顺序
- MySQL :从左往右去执行 WHERE 条件的。
- Oracle :从右往左去执行 WHERE 条件的。
写WHERE条件的时候,优先级高的部分要去编写过滤力度最大的条件语句
相关文章:
mysql-4:SQL的解析顺序
SQL语句的解析顺序 文章目录 SQL语句的解析顺序编写顺序与解析顺序解析顺序关键字FROMONOUTER JOINWHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT 解析流程流程分析流程说明WHERE条件解析顺序 编写顺序与解析顺序 编写顺序 SELECT DISTINCT < select_list > FROM &l…...
如何通过优化Read-Retry机制降低SSD读延迟?
近日,小编发现发表于2021论文中,有关于优化Read-Retry机制降低SSD读延迟的研究,小编这里给大家分享一下这篇论文的核心的思路,感兴趣的同学可以,可以在【存储随笔】VX公号后台回复“Optimizing Read-Retry”获取下载链接。 本文中主要基于Charge Trap NAND架构分析。NAND基…...
matlab自动生成FPGA rom源码
1 matlab 源码 close all clear all clci=0:1:(300000-100-1); x=300000./(100+i); x=x./2; x=round(...
消息队列(RabbitMQ+RocketMQ+Kafka)
消息队列是一种应用程序之间通过异步通信进行数据交换的通信模式 消息队列的类型: 点对点,一对一的消息传递模型,其中每个消息只能被一个接收者消费。发送者将消息发送到队列中,而接收者从队列中获取消息并进行处理,…...
python判断语句
1.布尔类型 进行判断,只有是(True:本质上是一个数字,记作1)和否(False:本质上是一个数字,记作0)。 定义变量存储布尔类型数据: 变量名称 布尔类型字面量 a True代码演示: a True print(type(a))输出结…...
C# 虚方法
在C#中,虚方法(virtual methods)是一种允许派生类(子类)覆盖(重写)基类(父类)中的方法的技术。虚方法的定义和使用如下: 基类中定义虚方法: pub…...
微信小程序,动态设置三级联动, 省市区街道
1.第一步 传parentId0 查询省份 2.第二步 选择省份,传pathId选择省份的pathId, 不传parentId,会查询出 市/县数据 3.第三步 根据选择县的parentId 查询街道数据,传parentId选择的县id 4.选择结果回显 显示所选择的 path 以/分割 取最后一级<van-dropdown-menu…...
Learn Prompt- Midjourney 图片生成:Image Prompts
Prompt 自动生成 前不久,Midjourney 宣布支持图片转 prompt 功能。 原始图片 blueprint holographic design of futuristic Midlibrary --v 5Prompt 生成 直接输入 /describe 指令通过弹出窗口上传图像并发送,Midjourney 会根据该图像生成四种可…...
基于微信小程序的健身房私教预约平台设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言系统主要功能:具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…...
安卓Compose(二)
在上一篇博客中,我们已经了解了安卓Compose的一些基本概念以及使用方法,接下来我们将继续深入学习。 一、Compose的基础组件 文本组件(Text) 文本组件是Compose中最基本的组件之一,用于在界面上显示文本。使用方式如下: // 定…...
TCP 和 UDP哪个更好
传输控制协议 (TCP) 和用户数据报协议 (UDP) 是互联网的基础支柱,支持从网络源到目的地的不同类型的数据传输。TCP更可靠,而UDP优先考虑速度和效率。本文解释了两种协议的工作原理,并详细讨论了…...
Spring Boot 如何实现单点登录(SSO)
当今的应用程序越来越多地采用了微服务架构,这就引出了一个重要的问题:如何实现单点登录(Single Sign-On,简称SSO)来确保用户在多个微服务之间无需重复登录。Spring Boot是一个流行的Java框架,它提供了一些…...
C#中的(++)和(--)运算符
目录 背景: 的前加 效果展示: 的后加 效果展示 : 总结: 背景: 自增和自减运算符存在于C/C/C#/Java等高级语言中,它的作用是在运算结束前(前置自增自减运算符 )或后(后置自增自减运算符 )将 变量的值加(或减)1。 在C#中,和--是自增和自减运…...
SVG鼠标漫游
鼠标漫游 鼠标漫游就是通过移动光标和滚轮,完成画布缩放、移动的交互过程。 svg 绘图使用原点在左上角的坐标系统,一个单位代表一像素。这里的像素不能简单理解为屏幕像素,是一个用户单位。svg 的 width 和 height 属性决定图像在用户系统的…...
关于Github报SSL_ERROR_SYSCALL的解决方案
最近在运行RN项目的时候发现,在我pod install命令安装pod包时产生了 SSL_ERROR_SYSCALL 的错误,如下所示。 [!] Error installing CocoaAsyncSocket [!] /usr/bin/git clone https://github.com/robbiehanson/CocoaAsyncSocket.git /var/folders/v0/2435fl9178sd4r2_1mdgk_r…...
Redis 集群搭建教程
一、介绍 Redis 集群有着高可用、易扩展、更好的性能等优势,本文主要是实战搭建一个三主三从的 Redis 集群。 正常来说,搭建 Redis 集群需要 6 台服务器。为了简单一点,本文通过一台服务器,6 个端口,搭建一个 Redis …...
图形处理软件Photoshop Elements 2020 mac中文版 ps简化版
Photoshop Elements 2020 mac是一款非常实用的图形处理工具。ps elements 2020 mac中文版可以帮助您自动生成照片和视频作品的功能,采用Adobe Sensei AI技术可进行图像组织、编辑和创建等。Photoshop Elements 2020 for Mac激活版可以帮助您轻松整理照片和视频&…...
opencv for unity package在unity中打开相机不需要dll
下载OpenCV for Unity 导入后,里面有很多案例 直接打开就可以运行 打开相机...
[Linux入门]---进程状态
文章目录 1.进程主要状态进程运行状态进程阻塞状态进程的挂起状态 2.Linux进程状态Linux进程内核源代码①R运行状态②S睡眠状态③D磁盘休眠状态T停止状态④X死亡状态⑤Z僵尸状态⑥孤儿进程 3.总结 1.进程主要状态 进程运行状态 ①内存中有一个运行队列,其中有两个指…...
腾讯mini项目-【指标监控服务重构】2023-08-29
今日已办 Collector 指标聚合 由于没有找到 Prometheus 官方提供的可以聚合指定时间区间内的聚合函数,所以自己对接Prometheus的api来聚合指定容器的cpu_avg、cpu_99th、mem_avg 实现成功后对接小组成员测试完提供的时间序列和相关容器,将数据记录在表格…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
