mysql左连接出现笛卡尔积_Mysql内连接、左连接会出现笛卡尔积的理解
先简单解释一下笛卡尔积。
现在,我们有两个集合A和B。
A = {0,1} B = {2,3,4}
集合 A×B 和 B×A的结果集就可以分别表示为以下这种形式:
A×B = {(0,2),(1,2),(0,3),(1,3),(0,4),(1,4)};
B×A = {(2,0),(2,1),(3,0),(3,1),(4,0),(4,1)};
以上A×B和B×A的结果就可以叫做两个集合相乘的‘笛卡尔积’。
从以上的数据分析我们可以得出以下两点结论:
1,两个集合相乘,不满足交换率,既 A×B ≠ B×A;
2,A集合和B集合相乘,包含了集合A中元素和集合B中元素相结合的所有的可能性。既两个集合相乘得到的新集合的元素个数是 A集合的元素个数 × B集合的元素个数;
MySQL的多表查询(笛卡尔积原理)先确定数据要用到哪些表。
将多个表先通过笛卡尔积变成一个表。
然后去除不符合逻辑的数据(根据两个表的关系去掉)。
最后当做是一个虚拟表一样来加上条件即可。
数据库表连接数据行匹配时所遵循的算法就是以上提到的笛卡尔积,表与表之间的连接可以看成是在做乘法运算。
比如现在数据库中有两张表,student表和 student_subject表,如下所示:
我们执行以下的sql语句,只是纯粹的进行表连接。
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
看一下执行结果:
表1.0 表1.1
从执行结果上来看,结果符合我们以上提出的两点结论(红线标注部分);
以第一条sql语句为例我们来看一下他的执行流程,
1,from语句把student表 和 student_subject表从数据库文件加载到内存中。
2,join语句相当于对两张表做了乘法运算,把student表中的每一行记录按照顺序和student_subject表中记录依次匹配。
3,匹配完成后,我们得到了一张有 (student中记录数 × student_subject表中记录数)条的临时表。 在内存中形成的临时表如表1.0所示。我们又把内存中表1.0所示的表称为‘笛卡尔积表’。
针对以上的理论,我们提出一个问题,难道表连接的时候都要先形成一张笛卡尔积表吗,如果两张表的数据量都比较大的话,那样就会占用很大的内存空间这显然是不合理的。所以,我们在进行表连接查询的时候一般都会使用JOIN xxx ON xxx的语法,ON语句的执行是在JOIN语句之前的,也就是说两张表数据行之间进行匹配的时候,会先判断数据行是否符合ON语句后面的条件,再决定是否JOIN。
因此,有一个显而易见的SQL优化的方案是,当两张表的数据量比较大,又需要连接查询时,应该使用 FROM table1 JOIN table2 ON xxx的语法,避免使用 FROM table1,table2 WHERE xxx 的语法,因为后者会在内存中先生成一张数据量比较大的笛卡尔积表,增加了内存的开销。
下面引出Mysql的左右连接和内连接的笛卡尔积...
一个同事跟我讨论左连接查询,是不是笛卡尔积。我第一反应,左连接肯定不是笛卡尔积啊,左连接是以左表为准,左表有m条记录,则结果集是m条记录(哈哈,如果是你,你是不是也是这样的反映),同事听了,说内连接会是笛卡尔积。在数据库里试验了一下,发现,事实比想象中要复杂。
首先说下结论:链接查询,如果on条件是非唯一字段,会出现笛卡尔积(局部笛卡尔积);如果on条件是表的唯一字段,则不会出现笛卡尔积。
下面是具体的试验:(以真三国无双v3.9d蜀国阵容为例...)
文中会有两张表,user表和job表,表数据如下,其中user为5条记录,job为4条记录
USER:
job:
1.交叉连接
如果A表有m(5)条记录,m1条符合on条件,B表有n(4)条记录,有n1条符合on条件,无条件交叉连接的结果为: m*n=5*4=20
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
这种等同于(交叉查询等于不加on的内连接)
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
sql执行结果:总共20条记录
结论:交叉连接,会产生笛卡尔积。
2.内连接(可以当做左连接的特殊情况,只保留符合主表中on条件的记录)
(1)内连接唯一字段
如果A表有m(5)条记录,m1(4)条符合on条件,B表有n(4)条记录,有n1(3)条符合on条件,内连接唯一字段结果为:Max(m1,n1)=4
1,2,2,6,7 和 1,2,7,8对比,以user表为主表,因为主表中有4条符合条件的记录(1,2,2,7),而job表有3条符合条件的记录(1,2,7),取两者中的最大的,所以为4条
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
sql执行结果为:4条记录
结论:假如,内连接查询,on条件是A表或者B表的唯一字段,则结果集是两表的交集,不是笛卡尔积。
(2)内连接非唯一字段
如果A表有m(5)条记录,m1(2)条符合on条件,B表有n(4)条记录,有n1(3)条符合on条件,则结果集是Max(m1,n1)=3条
1,2,2,6,7 和 1,1,7,8对比,以user表为主表,因为主表中有2条符合条件的记录(1,7),而job表有3条符合条件的记录(1,1,7),取两者中的最大的,所以为3条
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
结论:假如,on条件是表中非唯一字段,则结果集是两表匹配到的结果集的笛卡尔积(局部笛卡尔积) 。
3.外连接
(1)左连接
a.左连接唯一字段
假如A表有m(5)条记录,B表有n(4)条记录,则结果集是m=5
1,2,2,6,7 和 1,2,7,8对比,以user表为主表,因为主表中有4条符合条件的记录(1,2,2,7),而job表有3条符合条件的记录(1,2,7),取两者中的最大的,所以取4条,然后再加上user表中没有在job表中找到对应关系的记录(即对应的job表都为null,5-4=1),所以最终结果为4+1=5条
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
SQL查询结果:5条记录
结论:on条件是唯一字段,则结果集是左表记录的数量。
b.左连接非唯一字段
1,2,2,6,7 和 1,1,7,8对比,以user表为主表,因为主表中有2条符合条件的记录(1,7),而job表有3条符合条件的记录(1,1,7),取两者中的最大的,所以取3条,然后在加上user表在job表中没有匹配的记录(即对应的job表都为null,为5-2=3),所以最终结果为3+3=6条
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
结论:左连接非唯一字段,是局部笛卡尔积。
c.当on 条件为假时的内连接:
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
sql查询结果:5条
结论:当on条件为假的时候,即user在job表中一条符合记录的都没有,那么即为:user表中的所有记录条数,所以为5条,job表中的值都为null
(2)右连接
同左连接,这里就不赘述了
全外连接
mysql不支持
总结:左右连接是否产生笛卡尔积,和on的条件是否为唯一索引没有关系,只和左表、右表两者各自匹配on条件的记录条数有关系(左连接和右连接可以这么做:1:由INNER JOIN查询全匹配记录;2:查询左表或者右表没有符合on条件的记录;3.全匹配记录+没有匹配上的记录就是左连接或者右连接查询的结果集)
1.全匹配:
无论哪种查询,首先计算出on匹配记录(FROM user INNER JOIN job ON ...或者使用 FROM user,job where...),匹配记录的查询结果为:若A表有m条记录,符合on查询条件的为m1条,B表有n条记录,符合on条件的为n1条,那么匹配记录为MAX(m1,n1);
2.左连接:
结果集为:MAX(m1,n1)+(m-m1);
如果m1 > n1,则不会产生笛卡尔积,因为无论不匹配的记录(m-m1),还是匹配的记录MAX(m1,n1),都是从左表中取记录,所以不会出现重复的记录;反之,如果m1 < n1,则一定会产生笛卡尔积,因为MAX(m1,n1)是从右表中取的,而根据笛卡尔积的原理,右表中的每条记录都会和左表中的所有记录匹配一次,所以符合on条件的n1条记录也一定会和左表中的所有记录都匹配一次,而左表中符合记录只有m1条,所以造成笛卡尔积的条数为(n1-m1)条
即用内连接的记录(MAX(m1,n1)),加上左表没有满足on条件的记录(m-m1),所以为:MAX(m1,n1)+(m-m1);
3.有连接
结果集为:MAX(m1,n1)+(n-n1);
如果m1 n1,则一定会产生笛卡尔积,因为MAX(m1,n1)是从左表中取的,所以造成笛卡尔积的记录条数为(m1-n1)条
即用内连接的记录(MAX(m1,n1)),加上右表没有满足on条件的记录(n-n1),所以为:MAX(m1,n1)+(n-n1);
下面再来谈下:
Mysql:ON 与 WHERE 的区别
很多同学在学习 Mysql 表关联的时候弄不清 ON 与 WHERE 的区别,不知道条件应该写在 ON 里面还是 WHERE 里面,作者在工作的时候也入过坑,总觉得条件写在哪里查询结果都是一样的,最后出错坏了事,差点惹了大祸。所以今天简单易懂的总结一下他们的区别,大家共同学习。
准备工作
我们先准备两个表,并造一些数据:
表t1:
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
表t2:
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
查询结果如图:
表t1记录:
表t2记录:
探究
口诀:先执行 ON,后执行 WHERE;ON 是建立关联关系,WHERE 是对关联关系的筛选。
记住这句话就可以准确地判断查询结果了,我们通过两个 sql 来进行分析:
SQL1:
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
前提是 LEFT JOIN,所以左边的数据在创建关联关系时会保留,根据口诀,先执行 ON 建立关联关系,形成子表,最后在子表中通过 WHERE 筛选,过程如下:
左表符合记录的t1.id = t2.id的记录有2条,右表符合记录的有4条,所以MAX(m1,n1)为4条,其中左表没有符合on条件的记录为(3-2=1)条,所以LEFT JOIN的结果总共有5条,最后一条左表没有匹配上右表记录,所以右表的属性都为null,如下:
但是最终结果从5条记录中再通过where进行筛选,即matches为2,所以结果只有2条(注意先LEFT JOIN,然后再是where,所以此时5条记录中不符合where条件的记录会被排除,即最终的结果不再是左表所有的记录):
SQL2:
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
SQL2没有 WHERE,那么 ON 建立的关联关系就是最终结果(因为没有where条件进行最终筛选,所有最终结果为内联记录加上左表中没有符合on条件的记录):
符合ON条件的记录,改为内联INNER JOIN ,查询基础数据:MAX(m1,n1)
当前内容已被隐藏,您需要登录才能查看快速登录快速注册
所以MAX(m1,n1)为2条,结果为:
再由基础数据加上左表没有匹配上的记录数(只有id为3的没有匹配上,即(n-n1) = 1)只有1条,所以最终结果为:
最终结果为:MAX(m1,n1)+(m-m1) = 2 + (id为3的记录) = 3条
通过这两个 sql 可以很好的区分 WHERE 和 ON 的区别了,希望大家使用的时候多注意这一点,避免犯错!
mysql左连接出现笛卡尔积_Mysql内连接、左连接会出现笛卡尔积的理解相关推荐
- mysql内连接的自连接_mysql 内连接、外连接、自连接
一)内连接(等值连接):查询客户姓名,订单编号,订单价格 --------------------------------------------------- select c.name,o.isb ...
- mysql长时间后断开_mysql 长时间没连接了 就会自动断开服务
这是因为mysql 长时间没连接了 就会自动断开服务. 解决办法 1.首先,下载必须的jar包 dbcp 包,目前版本是1.2.1:http://jakarta.apache.org/commons/ ...
- mysql 笛卡尔积_Mysql内连接、左连接会出现笛卡尔积的理解
先简单解释一下笛卡尔积. 现在,我们有两个集合A和B. A = {0,1} B = {2,3,4} 集合 A×B 和 B×A的结果集就可以分别表示为以下这种形式: A×B = {(0,2),( ...
- mysql left join 三表查询_MySql的join(连接)查询 (三表 left join 写法)
1.内连接:将两个表中存在连结关系的字段符合连接条件的记录形成记录集 Select A.name,B.name from A inner join B on A.id=B.id和 Select A.n ...
- mysql outer join的用法_MySQL 8 中的连接语法JOIN、OUTER JOIN的相关用法
JOIN连接为内连接(INNER JOIN),如果A表与B表进行JOIN连接,都是查询这两个表的交集,所谓交集就是这条记录既在A表中存在也在B表中存在:mysql> SELECT a.id, a ...
- mysql如何开启远程链接_mysql怎么开启远程连接
匿名用户 1级 2017-12-14 回答 一.连接远程数据库: 1.显示密码 如:MySQL 连接远程数据库(192.168.5.116),端口"3306",用户名为" ...
- linux mysql 命令行查询 乱码_mysql命令提示行连接乱码的解决
解决MySQL命令行无法连接问题错误ERROR1045(28000) 问题现象: 用navicat可以连接数据库 通过命令行mysql -uroot -p 输入密码后提示"ERROR 104 ...
- mysql连接字符乱码_MySQL 字符集导致SQL连接之后中文乱码的问题!
character-set-server = GB2312 collation-server = latin1_general_ci MySQL字符集 GBK.GB2312.UTF8区别 解决 MYS ...
- mysql数据库中修改错别字_MYSQL 复杂查询超时连接 lost Error 与 错别字
最近的错别字是越来越厉害,上一篇开头就是两个错别字,恨得我要死,不检查,并且一边写一边查让写的语句也变得像是 translation的.所以最近在反思,数量和质量之间的问题,每周5天,天天一篇,虽然说 ...
最新文章
- zabbix-proxy分布式监控配置
- 《MapReduce 2.0源码分析与编程实战》一第1章 HBase介绍
- char,Character,int,字符及编码日记
- 某程序的bug是什么意思?
- jfinal配置rails的数据表
- 【Java自顶向下】HashMap面试题(2021最新版)
- 【数据分析实例】1000 万条淘宝用户行为数据实时分析
- SQLServer数据库文件相关知识笔记
- jsp servlet中的过滤器Filter配置总结(转)
- centos8安装mysql5.5_CentOS 6.8 编译安装MySQL5.5.32 (二 多实例)
- 【李宏毅2020 ML/DL】P110-111 Policy Gradient Proximal Policy Optimization
- Java多线程实现-Runnable接口
- H.265编码原理入门
- python快递价格查询系统
- ROS | 基于MQTT的通信方式mqtt_bridge
- Embedding Propagation: Smoother Manifold for Few-Shot Classification ECCV 2020
- 【kimol君的无聊小发明】—用python插入独创性声明
- C#使用 MailKit获取邮件中的附件(QQ邮箱/163网易邮箱)
- 【vscode 插件】为 markdown 文章标题自动添加多级序号
- 如何使用爬虫与JieBa库制作词云