连接的原理(待修改)

搞数据库⼀个避不开的概念就是Join,翻译成中⽂就是连接。

相信很多⼩伙伴在初学连接的时候有些⼀脸懵逼,理解了连接的语义之后⼜可能不明⽩各个表中的记 录到底是怎么连起来的,以⾄于在使⽤的时候常常陷⼊下边两种误区:

误区⼀:业务⾄上,管他三七⼆⼗⼀,再复杂的查询也⽤在⼀个连接语句中搞定。

误区⼆:敬⽽远之,上次 DBA 那给报过来的慢查询就是因为使⽤了连接导致的,以后再也不敢⽤了。

连接简介 连接的本质 为了故事的顺利发展,我们先建⽴两个简单的表并给它们填充⼀点数据:

mysql> CREATE TABLE t1 (m1 int, n1 char(1));

Query OK, 0 rows affected (0.02 sec)

mysql> CREATE TABLE t2 (m2 int, n2 char(1));

Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO t1 VALUES(1, 'a'), (2, 'b'), (3, 'c');

Query OK, 3 rows affected (0.00 sec) Records: 3  Duplicates: 0  Warnings: 0

mysql> INSERT INTO t2 VALUES(2, 'b'), (3, 'c'), (4, 'd');

Query OK, 3 rows affected (0.00 sec) Records: 3  Duplicates: 0  Warnings: 0

我们成功建⽴了t1、t2两个表,这两个表都有两个列,⼀个是INT类型的,⼀个是CHAR(1)类型的,填充好数据的两个表⻓这样:

mysql> SELECT * FROM t1;

+------+------+

| m1   | n1   |

+------+------+

|    1 | a    |

|    2 | b    |

|    3 | c    |

+------+------+

3 rows inset (0.00 sec)

mysql> SELECT * FROM t2;

+------+------+

| m2   | n2   |

+------+------+

|    2 | b    |

|    3 | c    |

|    4 | d    |

+------+------+

3 rows inset (0.00 sec)

连接的本质就是把各个连接表中的记录都取出来依次匹配的组合加⼊结果集并返回给⽤户。所以我们把t1和t2两个表连接起来的过程如下图所示:

这个过程看起来就是把t1表的记录和t2的记录连起来组成新的更⼤的记录,所以这个查询过程称之为连接查询。连接查询的结果集中包含⼀个表中的每⼀条记录 与另⼀个表中的每⼀条记录相互匹配的组合,像这样的结果集就可以称之为笛卡尔积。因为表t1中有3条记录,表t2中也有3条记录,所以这两个表连接之后的笛卡 尔积就有3×3=9⾏记录。在MySQL中,连接查询的语法也很随意,只要在FROM语句后边跟多个表名就好了,⽐如我们把t1表和t2表连接起来的查询语句可以写成这 样:

 

连接过程简介

如果我们乐意,我们可以连接任意数量张表,但是如果没有任何限制条件的话,这些表连接起来产⽣的笛卡尔积可能是⾮常巨⼤的。⽐⽅说3个100⾏记录的表连接 起来产⽣的笛卡尔积就有100×100×100=1000000⾏数据!所以在连接的时候过滤掉特定记录组合是有必要的,在连接查询中的过滤条件可以分成两种:

涉及单表的条件

这种只设计单表的过滤条件我们之前都提到过⼀万遍了,我们之前也⼀直称为搜索条件,⽐如t1.m1 > 1是只针对t1表的过滤条件,t2.n2 < 'd'是只针对t2表 的过滤条件。

涉及两表的条件

这种过滤条件我们之前没⻅过,⽐如t1.m1 = t2.m2、t1.n1 > t2.n2等,这些条件中涉及到了两个表,我们稍后会仔细分析这种过滤条件是如何使⽤的哈。 下边我们就要看⼀下携带过滤条件的连接查询的⼤致执⾏过程了,⽐⽅说下边这个查询语句

SELECT * FROM t1, t2 WHERE t1.m1 > 1 AND t1.m1 = t2.m2 AND t2.n2 < 'd';

在这个查询中我们指明了这三个过滤条件:

t1.m1 > 1

t1.m1 = t2.m2

t2.n2 < 'd'

那么这个连接查询的⼤致执⾏过程如下:

1. ⾸先确定第⼀个需要查询的表,这个表称之为驱动表。怎样在单表中执⾏查询语句我们在前⼀章都唠叨过了,只需要选取代价最⼩的那种访问⽅法去执⾏单表 查询语句就好了(就是说从const、ref、ref_or_null、range、index、all这些执⾏⽅法中选取代价最⼩的去执⾏查询)。此处假设使⽤t1作为驱动表,那么就 需要到t1表中找满⾜t1.m1 > 1的记录,因为表中的数据太少,我们也没在表上建⽴⼆级索引,所以此处查询t1表的访问⽅法就设定为all吧,也就是采⽤全 表扫描的⽅式执⾏单表查询。关于如何提升连接查询的性能我们之后再说,现在先把基本概念捋清楚哈。所以查询过程就如下图所示:

我们可以看到,t1表中符合t1.m1 > 1的记录有两条。

2. 针对上⼀步骤中从驱动表产⽣的结果集中的每⼀条记录,分别需要到t2表中查找匹配的记录,所谓匹配的记录,指的是符合过滤条件的记录。因为是根据 t1表中的记录去找t2表中的记录,所以t2表也可以被称之为被驱动表。上⼀步骤从驱动表中得到了2条记录,所以需要查询2次t2表。此时涉及两个表的 列的过滤条件t1.m1 = t2.m2就派上⽤场了:

当t1.m1 = 2时,过滤条件t1.m1 = t2.m2就相当于t2.m2 = 2,所以此时t2表相当于有了t2.m2 = 2、t2.n2 < 'd'这两个过滤条件,然后到t2表中 执⾏单表查询。

当t1.m1 = 3时,过滤条件t1.m1 = t2.m2就相当于t2.m2 = 3,所以此时t2表相当于有了t2.m2 = 3、t2.n2 < 'd'这两个过滤条件,然后到t2表中 执⾏单表查询。

所以整个连接查询的执⾏过程就如下图所示: 

 

 从上边两个步骤可以看出来,我们上边唠叨的这个两表连接查询共需要查询1次t1表,2次t2表。当然这是在特定的过滤条件下的结果,如果我们把t1.m1 > 1 这个条件去掉,那么从t1表中查出的记录就有3条,就需要查询3次t2表了。也就是说在两表连接查询中,驱动表只需要访问⼀次,被驱动表可能被访问多 次。

内连接和外连接

为了⼤家更好理解后边内容,我们先创建两个有现实意义的表,

CREATE TABLE student (    

number INT NOT NULL AUTO_INCREMENT COMMENT '学号',    

name VARCHAR(5) COMMENT '姓名',    

major VARCHAR(30) COMMENT '专业',    

PRIMARY KEY (number) ) Engine=InnoDB CHARSET=utf8 COMMENT '学⽣信息表';

CREATE TABLE score (    

number INT COMMENT '学号',    

subject VARCHAR(30) COMMENT '科⽬',    

score TINYINT COMMENT '成绩',    

PRIMARY KEY (number, score) ) Engine=InnoDB CHARSET=utf8 COMMENT '学⽣成绩表';

我们新建了⼀个学⽣信息表,⼀个学⽣成绩表,然后我们向上述两个表中插⼊⼀些数据,为节省篇幅,具体插⼊过程就不唠叨了,插⼊后两表中的数据如下:

 

 现在我们想把每个学⽣的考试成绩都查询出来就需要进⾏两表连接了(因为score中没有姓名信息,所以不能单纯只查询score表)。连接过程就是从student 表中取出记录,在score表中查找number相同的成绩记录,所以过滤条件就是student.number = socre.number,整个查询语句就是这样:

mysql> SELECT * FROM student, score WHERE student.number = score.number;

 

 字段有点多哦,我们少查询⼏个字段:

 从上述查询结果中我们可以看到,各个同学对应的各科成绩就都被查出来了,可是有个问题,史珍⾹同学,也就是学号为20180103的同学因为某些原因没有参 加考试,所以在score表中没有对应的成绩记录。那如果⽼师想查看所有同学的考试成绩,即使是缺考的同学也应该展示出来,但是到⽬前为⽌我们介绍的连 接查询是⽆法完成这样的需求的。我们稍微思考⼀下这个需求,其本质是想:驱动表中的记录即使在被驱动表中没有匹配的记录,也仍然需要加⼊到结果集。 为了解决这个问题,就有了内连接和外连接的概念:

对于内连接的两个表,驱动表中的记录在被驱动表中找不到匹配的记录,该记录不会加⼊到最后的结果集,我们上边提到的连接都是所谓的内连接。

对于外连接的两个表,驱动表中的记录即使在被驱动表中没有匹配的记录,也仍然需要加⼊到结果集。

在MySQL中,根据选取驱动表的不同,外连接仍然可以细分为2种:

左外连接

选取左侧的表为驱动表。

右外连接

选取右侧的表为驱动表。

可是这样仍然存在问题,即使对于外连接来说,有时候我们也并不想把驱动表的全部记录都加⼊到最后的结果集。这就犯难了,有时候匹配失败要加⼊结果 集,有时候⼜不要加⼊结果集,这咋办,有点⼉愁啊。。。噫,把过滤条件分为两种不就解决了这个问题了么,所以放在不同地⽅的过滤条件是有不同语义 的:

WHERE⼦句中的过滤条件

WHERE⼦句中的过滤条件就是我们平时⻅的那种,不论是内连接还是外连接,凡是不符合WHERE⼦句中的过滤条件的记录都不会被加⼊最后的结果集。

ON⼦句中的过滤条件

对于外连接的驱动表的记录来说,如果⽆法在被驱动表中找到匹配ON⼦句中的过滤条件的记录,那么该记录仍然会被加⼊到结果集中,对应的被驱动表记 录的各个字段使⽤NULL值填充。

需要注意的是,这个ON⼦句是专⻔为外连接驱动表中的记录在被驱动表找不到匹配记录时应不应该把该记录加⼊结果集这个场景下提出的,所以如果把ON ⼦句放到内连接中,MySQL会把它和WHERE⼦句⼀样对待,也就是说:内连接中的WHERE⼦句和ON⼦句是等价的。

⼀般情况下,我们都把只涉及单表的过滤条件放到WHERE⼦句中,把涉及两表的过滤条件都放到ON⼦句中,我们也⼀般把放到ON⼦句中的过滤条件也称之为连 接条件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/166317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux磁盘清理

目录 排查过程1、查看磁盘占用情况2. 按照占用大小进行倒排-当前目录及其子目录3.当前目录磁盘占用情况 清理命令 排查过程 1、查看磁盘占用情况 df -hdf -h 命令用于显示磁盘空间的使用情况&#xff0c;以人类可读的方式呈现&#xff0c;其中&#xff1a;df 是 “disk free”…

“AI就绪”新计划,亚马逊云科技到2025年向200万人提供免费AI技能培训

AI就绪&#xff08;AI Ready&#xff09;计划 到2025年为全球200万人提供 免费人工智能&#xff08;AI&#xff09;技能培训和教育资源 亚马逊云科技宣布启动“AI就绪&#xff08;AI Ready&#xff09;”计划&#xff0c;旨在到2025年为全球200万人提供免费人工智能&#xff08…

易点易动固定资产管理系统:全生命周期管理的理想选择

在现代企业中&#xff0c;固定资产管理是一项至关重要的任务。为了确保企业的资产安全、提高资产利用率&#xff0c;全面管理固定资产的生命周期至关重要。易点易动固定资产管理系统为企业提供了一种全面的解决方案&#xff0c;实现了从固定资产申购、采购、入库、领用、退库、…

linux 内存回收mglru算法代码注释2

mglru与原lru算法的兼容 旧的lru算法有active与inactive两代lru&#xff0c;可参考linux 内存回收代码注释&#xff08;未实现多代lru版本&#xff09;-CSDN博客 新的算法在引入4代lru的同时&#xff0c;还引入了tier的概念。 新旧算法的切换的实现在lru_gen_change_state&a…

ELK企业级日志分析平台——elasticsearch

集群部署 文档&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/7.6/index.html 下载&#xff1a;https://elasticsearch.cn/download/ 主机 ip 角色 k8s1 192.168.92.11 cerebro elk1 192.168.92.31 elasticsearch elk2 192.168.92.32 elasti…

数据库实验五 数据库设计

数据库实验五 数据库设计 一、实验目的二、实验内容三、实验内容四、验证性实验五、设计性实验 一、实验目的 1.了解E-R图构成要素以及各要素图元。 2.掌握概念模型E-R图的绘制方法。 3.掌握概念模型向逻辑模型的转换原则和步骤。 4.运用sql编程实现 二、实验内容 1.选取一个…

医院手术麻醉信息系统全套源码,自主版权,支持二次开发

医院手术麻醉信息系统全套商业源码&#xff0c;自主版权&#xff0c;支持二次开发 手术麻醉信息系统是HIS产品的中的一个组成部分&#xff0c;主要应用于医院的麻醉科&#xff0c;属于电子病历类产品。医院麻醉监护的功能覆盖整个手术与麻醉的全过程&#xff0c;包括手术申请与…

人工智能中的文本分类:技术突破与实战指导

在本文中&#xff0c;我们全面探讨了文本分类技术的发展历程、基本原理、关键技术、深度学习的应用&#xff0c;以及从RNN到Transformer的技术演进。文章详细介绍了各种模型的原理和实战应用&#xff0c;旨在提供对文本分类技术深入理解的全面视角。 关注TechLead&#xff0c;分…

回归预测 | MATLAB实现SCN随机配置网络多输入单输出回归预测

回归预测 | MATLAB实现SCN随机配置网络多输入单输出回归预测 目录 回归预测 | MATLAB实现SCN随机配置网络多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现SCN随机配置网络多变量回归预测 1.data为数据集&#xff0c;7个输入特征&#xff0…

基于Python实现汽车销售数据可视化+预测【500010086.1】

导入模块 import numpy as np import pandas as pd from pylab import mpl import plotly.express as px import matplotlib.pyplot as plt import seaborn as sns设置全局字体 plt.rcParams[font.sans-serif][kaiti]获取数据 total_sales_df pd.read_excel(r"./data/中…

机器学习第13天:模型性能评估指标

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 交叉验证 保留交叉验证 k-折交叉验证 留一交叉验证 混淆矩阵 精度与召回率 介绍 精度 召回率 区别 使用代码 偏差与方差 介绍 区…

zerotier 搭建 moon中转服务器 及 自建planet

搭建moon 服务器 环境准备 # 安装依赖 yum install wget gcc gcc-c git -y yum install json-devel -y# 下载及安装 curl -s https://install.zerotier.com/ | sudo bash节点ID 配置 配置moon.json文件 cd /var/lib/zerotier-one/# 导出依赖 zerotier-idtool initmoon ide…

SpringBoot项目连接,有Kerberos认证的Kafka

在连接Kerberos认证kafka之前&#xff0c;需要了解Kerberos协议 二、什么是Kerberos协议 Kerberos是一种计算机网络认证协议 &#xff0c;其设计目标是通过密钥系统为网络中通信的客户机(Client)/服务器(Server)应用程序提供严格的身份验证服务&#xff0c;确保通信双方身份的真…

历时三个月,我发布了一款外卖返钱小程序

近几年&#xff0c;推广外卖红包爆火&#xff0c;各种推广外卖红包的公众号层出不穷。于是&#xff0c;我就在想外卖红包究竟是怎么一回事。就这样&#xff0c;我带着问题开始了关于外卖红包的研究。 在研究的过程中&#xff0c;我开始了解商品联盟、推广分成、cps等一系列相关…

Springboot3+vue3从0到1开发实战项目(一)

一. 可以在本项目里面自由发挥拓展 二. 知识整合项目使用到的技术 后端开发 &#xff1a; Validation, Mybatis,Redis, Junit,SpringBoot3 &#xff0c;mysql&#xff0c;Swagger, JDK17 &#xff0c;项目部署 前端开发&#xff1a; Vue3&#xff0c;Vite&#xff0c;Router…

DNS的各种进阶新玩法

你们好&#xff0c;我的网工朋友&#xff0c;今天和你聊聊DNS。 01 什么是DNS&#xff1f; mac地址诞生&#xff0c;可是太不容易记忆了&#xff0c;出现了简化了IP形式&#xff0c;它被直接暴露给外网不说&#xff0c;还让人类还是觉得比较麻烦&#xff0c;干脆用几个字母算了…

【Git】一文教你学会 submodule 的增、删、改、查

添加子模块 $ git submodule add <url> <path>url 为想要添加的子模块路径path 为子模块存放的本地路径 示例&#xff0c;添加 r-tinymaix 为子模块到主仓库 ./sdk/packages/online-packages/r-tinymaix 路径下&#xff0c;命令如下所示&#xff1a; $ git subm…

用自己热爱的事赚钱,是多么的幸福

挖掘天赋可能有些困难&#xff0c;但挖掘爱好就简单多啦&#xff01;最幸福的事情就是能用自己喜欢的事情赚钱。 我们要说的是一个博主&#xff0c;他非常喜欢骑自行车&#xff0c;虽然他的工作是在外贸公司做销售&#xff0c;但每当有空时&#xff0c;他都会骑自行车。而且他…

Go iota简介

当声明枚举类型或定义一组相关常量时&#xff0c;Go语言中的iota关键字可以帮助我们简化代码并自动生成递增的值。本文档将详细介绍iota的用法和行为。 iota关键字 iota是Go语言中的一个预定义标识符&#xff0c;它用于创建自增的无类型整数常量。iota的行为类似于一个计数器…

3款免费次数多且功能又强大的国产AI绘画工具

hi&#xff0c;同学们&#xff0c;本期是我们第55 期 AI工具教程 最近两个月&#xff0c;国内很多AI绘画软件被关停&#xff0c;国外绝大部分AI绘画工具费用不低&#xff0c;因此 这两天我 重新整理 国产 AI绘画 工具 &#xff0c; 最终 筛选了 3款功能强大&#xf…