工作总结之因为笛卡尔积问题写SQL搞了半天[害](附笛卡尔积总结)_笛卡尔积sql(1)

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

SUBSTR(b.SSFJH, 1, 6),
CONCAT(b.SSQY, b.LDMC) LDMC,
COUNT(b.SSFJH),
NULL SSLX

FROM
b
GROUP BY
SUBSTR(b.SSFJH, 1, 6),
b.SSQY,
b.LDMC


### 多表连接简介


在[关系数据库](https://bbs.youkuaiyun.com/topics/618545628)中,一个查询往往会涉及多个表,因为很少有数据库只有一个表,而如果大多查询只涉及到一个表的,那么那个表也往往低于第三范式,存在大量冗余和异常。


因此,连接(Join)就是一种把多个表连接成一个表的重要手段.


比如简单两个表连接学生表(Student)和班级(Class)表,如图:


[![1](https://img-blog.csdnimg.cn/img_convert/e143b45a2dd0920b68d96245cf1e8994.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042245285.png)[![2](https://img-blog.csdnimg.cn/img_convert/b56cd75f844f7be20268cf0c696a531e.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042245756.png)


进行连接后如图:


[![3](https://img-blog.csdnimg.cn/img_convert/e6b47f5c1dff9239588625a4b3c15480.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042246952.png)


[笛卡尔积](https://bbs.youkuaiyun.com/topics/618545628)


笛卡尔积在SQL中的实现方式既是交叉连接(Cross Join)。所有连接方式都会先生成临时笛卡尔积表,笛卡尔积是关系代数里的一个概念,表示两个表中的每一行数据任意组合,上图中两个表连接即为笛卡尔积(交叉连接)


在实际应用中,笛卡尔积本身大多没有什么实际用处,只有在两个表连接时加上限制条件,才会有实际意义,下面看内连接


内连接


如果分步骤理解的话,内连接可以看做先对两个表进行了交叉连接后,再通过加上限制条件(SQL中通过关键字on)剔除不符合条件的行的子集,得到的结果就是内连接了.上面的图中,如果我加上限制条件


对于开篇中的两个表,假使查询语句如下:



	SELECT *

FROM [Class] c
inner join
[Student] s
on c.ClassID=s.StudentClassID


可以将上面查询语句进行分部理解,首先先将Class表和Student表进行交叉连接,生成如下表:


[![5](https://img-blog.csdnimg.cn/img_convert/e03594fb4c11b54226d01e1e3078cc51.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042247333.png)


然后通过on后面的限制条件,只选择那些StudentClassID和ClassID相等的列(上图中划了绿色的部分),最终,得到选择后的表的子集


当然,内连接on后面的限制条件不仅仅是等号,还可以使用比较运算符,包括了>(大于)、>=(大于或等于)、<=(小于或等于)、<(小于)、!>(不大于)、!<(不小于)和<>(不等于)。当然,限制条件所涉及的两个列的数据类型必须匹配.


对于上面的查询语句,如果将on后面限制条件由等于改为大于:



	SELECT *

FROM [Class] c
inner join
[Student] s
on c.ClassID>s.StudentClassID


则结果从第一步的笛卡尔积中筛选出那些ClassID大于StudentClassID的子集:


[![6](https://img-blog.csdnimg.cn/img_convert/0e54eb6c5f6537b08dc364800c4cec99.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042252648.png)


虽然上面连接后的表并没有什么实际意义,但这里仅仅作为DEMO使用:-)


关系演算


上面笛卡尔积的概念是关系代数中的概念,而我在前一篇文章中提到还有关系演算的查询方法.上面的关系代数是分布理解的,上面的语句推导过程是这样的:“对表Student和Class进行内连接,匹配所有ClassID和StudentClassID相等行,选择所有的列”


而关系演算法,更多关注的是我想要什么,比如说上面同样查询,用关系演算法思考的方式是“给我找到所有学生的信息,包括他们的班级信息,班级ID,学生ID,学生姓名”


用关系演算法的SQL查询语句如下:



	SELECT *

FROM [Class] c
,
[Student] s
where c.ClassID=s.StudentClassID


当然,查询后返回的结果是不会变的:


[![4](https://img-blog.csdnimg.cn/img_convert/d3726e076d5ea5b46935007a78c9034d.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042248562.png)


外连接


假设还是上面两个表,学生和班级.我在学生中添加一个名为Eric的学生,但出于某种原因忘了填写它的班级ID:


[![7](https://img-blog.csdnimg.cn/img_convert/bd45a79d1600235fb0351bd2828e7307.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042253554.png) [![2](https://img-blog.csdnimg.cn/img_convert/7d6bb9c6324a544a7b9712f83a25c3fa.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042253857.png)


当我想执行这样一条查询:给我取得所有学生的姓名和他们所属的班级:



	SELECT s.StudentName,c.ClassName 

FROM [fordemo].[dbo].[Student] s
inner join
[fordemo].[dbo].[Class] c
on
s.StudentClassID=c.ClassID


结果如下图:


[![8](https://img-blog.csdnimg.cn/img_convert/8b85b2639bb3486ce972abe838203c9a.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042254687.png)


可以看到,这个查询“丢失”了Eric…


这时就需要用到外连接,外连接可以使连接表的一方,或者双方不必遵守on后面的连接限制条件.这里把上面的查询语句中的inner join改为left outer join:



	SELECT s.StudentName,c.ClassName 

FROM [fordemo].[dbo].[Student] s
left outer join
[fordemo].[dbo].[Class] c
on
s.StudentClassID=c.ClassID


结果如下:


[![9](https://img-blog.csdnimg.cn/img_convert/3d0ffa83d37af869b4c1e1cf30c99ee9.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042255994.png)


Eric又重新出现.


右外连接


右外连接和左外连接的概念是相同的,只是顺序不同,对于上面查询语句,也可以改成:



	SELECT s.StudentName,c.ClassName 

FROM [fordemo].[dbo].[Class] c
right outer join
[fordemo].[dbo].[Student] s
on
s.StudentClassID=c.ClassID


效果和上面使用了左外连接的效果是一样的.


全外连接


全外连接是将左边和右边表每行都至少输出一次,用关键字”full outer join”进行连接,可以看作是左外连接和右外连接的结合.


自连接


谈到自连接,让我们首先从一个表和一个问题开始:


[![10](https://img-blog.csdnimg.cn/img_convert/0e63bf41696abb35043c48932cf4949b.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042255404.png)


上面员工表(Employee),因为经理也是员工的一种,所以将两种人放入一个表中,MangerID字段表示的是当前员工的直系经理的员工id.


现在,我的问题是,如何查找CareySon的经理的姓名?


可以看出,虽然数据存储在单张表中,但除了嵌套查询(这个会在后续文章中讲到),只有自连接可以做到.正确自连接语句如下:



	SELECT m.EmployeeName

FROM [fordemo].[dbo].[Employee] e
inner join [fordemo].[dbo].[Employee] m
on e.ManagerID=m.id and e.EmployeeName=‘Careyson’


在详细解释自连接的概念之前,请再看一个更能说明自连接应用之处的例子:


[![11](https://img-blog.csdnimg.cn/img_convert/56be25717ea3d3019e915ce98a486ad9.png)](http://www.2cto.com/uploadfile/2011/1212/20111212042256978.png)


这个表是一个出席会议记录的表,每一行表示出席会议的记录(这里,由于表简单,我就不用EmployeeID和MeetingID来表示了,用名称对于理解表更容易些)


好了,现在我的问题是:找出既参加“谈论项目进度”会议,又参加”讨论职业发展”会议的员工


乍一看上去很让人迷惑是吧,也许你看到这一句脑中第一印象会是:



	SELECT  EmployeeName

FROM [fordemo].[dbo].[MeettingRecord] m
where MeetingName=‘¨???¨¨’ and meetingName=‘¨???¨°???¤?é?1’




![img](https://img-blog.csdnimg.cn/img_convert/132cceeacbc49ff85d22a5d00ab27a97.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f21496e2744155e63c4fde57353a045.png)
![img](https://img-blog.csdnimg.cn/img_convert/fd18a694908753e7d71e86a142a57e2d.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618545628)**

-jsMaTBBI-1715784625714)]
[外链图片转存中...(img-B3hWF5Cf-1715784625714)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618545628)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值