03--SQLtie三言两语SQLtie链接(join)
本文将从连接的理论和语法讲起,结合具体的例子,详细分析 SQL 连接。
之前对数据库的连接操作似懂非懂,大概知道是什么东西,但是面试笔试的时候被虐成渣,讲不清连接到底是什么。吃一堑,长一智。这就是所谓的似懂非懂, 只是单纯的看书是没用的,只有亲自动手做实验才能彻底理解什么是连接。
连接类型与条件
SQL 中每一种连接操作都包括一个连接类型和连接条件。
连接类型
连接类型决定了如何处理连接条件不匹配的记录。
| 连接类型 | 返回结果 |
|---|---|
| inner join | 只包含左右表中满足连接条件的记录 |
| left outer join | 在内连接的基础上,加入左表中不与右表匹配的记录,剩余字段赋值为null |
| right outer join | 在内连接的基础上,加入右表中不与左表匹配的记录,剩余字段赋值为null |
| full outer join | 左外连接和右外连接的组合。 |
| cross join | 等价于没有连接条件的内连接(即产生笛卡尔乘积) |
关键字 inner 和 outer 是可选的,因为根据连接类型的其余内容我们可以判断出连接是内连接和外连接。简单来说就是:除了单独的 join 是内连接,其他都是外连接。
对外连接来说,连接条件是 必须的 ;但对内连接来说,连接条件是 可选的 (如果省略,将产生笛卡尔积)。
连接条件
连接条件决定两个表中哪些记录互相匹配以及连接结果中出现哪些属性。
| 连接条件 | 修饰位置 | 语义 |
|---|---|---|
| natural | 连接类型之前 | 连接两个表之间的所有公共字段相等的记录,合并相同的列 |
| on <谓词> | 连接类型之后 | 连接符合谓词的记录,不合并相同的列 |
| using(A1, A2,…,An) | 连接类型之后 | natural 语义的子集,只连接两个表中(A1,A2,..An)的公共字段,合并相同的列 |
从上面的描述可以看到:连接操作是连接类型和连接条件的组合,只有在这个前提下才能真正的理解连接的功能。
FQA
例子中使用到的表
student +----+--------+
| id | name |
+----+--------+
| | 张三 |
| | 李四 |
| | 王二 |
| | 初一 |
| | 初二 |
+----+--------+
teacher +----+-----------+
| id | name |
+----+-----------+
| | 王老师 |
| | 李老师 |
| | 张老师 |
| | 肖老师 |
| | NULL |
| | 陈老师 |
+----+-----------+
course +----+--------+------+
| id | cname | tid |
+----+--------+------+
| | 数学 | |
| | 英语 | |
| | 语文 | |
| | 体育 | |
| | 物理 | NULL |
+----+--------+------+
student_course +-----+-----+
| sid | cid |
+-----+-----+
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
+-----+-----+
内连接之后的结果集数量是多少?等于左表或者右表中记录的数量吗?
内连接 teacher course 的结果
select * from teacher inner join course on teacher.id = course.tid;
+----+-----------+----+--------+------+
| id | name | id | cname | tid |
+----+-----------+----+--------+------+
| | 王老师 | | 数学 | |
| | 李老师 | | 英语 | |
| | 张老师 | | 语文 | |
| | 王老师 | | 体育 | |
+----+-----------+----+--------+------+
可以发现,王老师同时教数学和体育,因此左表中王老师匹配了右表中两条记录,物理没有老师教,所以没有出现在结果中。说明 内连接的结果集数量等于左右表中匹配记录的数量 。
左连接之后的结果集数量是多少?等于左表的记录数量吗?
左连接 teacher course 的结果
select * from teacher left join course on teacher.id = course.tid;
+----+-----------+------+--------+------+
| id | name | id | cname | tid |
+----+-----------+------+--------+------+
| | 王老师 | | 数学 | |
| | 李老师 | | 英语 | |
| | 张老师 | | 语文 | |
| | 王老师 | | 体育 | |
| | 肖老师 | NULL | NULL | NULL |
| | NULL | NULL | NULL | NULL |
| | 陈老师 | NULL | NULL | NULL |
+----+-----------+------+--------+------+
可以看到,没有教授课程的老师也出现在结果中,对应的字段都为NULL。说明结果集的数量并不等于左表记录的数量,因为两个表直接不是一对一的关系。其数量应该等于 内连接的结果集数量加上左表中不匹配的记录数量 。
Mysql 中不支持 full outer join
可以通过 union 操作模拟。
SELECT * FROM teacher
LEFT JOIN course ON teacher.id = course.tid
UNION
SELECT * FROM teacher
RIGHT JOIN course ON teacher.id = course.id; +------+-----------+------+--------+------+
| id | name | id | cname | tid |
+------+-----------+------+--------+------+
| | 王老师 | | 数学 | |
| | 李老师 | | 英语 | |
| | 张老师 | | 语文 | |
| | 王老师 | | 体育 | |
| | 肖老师 | NULL | NULL | NULL |
| | NULL | NULL | NULL | NULL |
| | 陈老师 | NULL | NULL | NULL |
| | 肖老师 | | 体育 | |
| | NULL | | 物理 | NULL |
+------+-----------+------+--------+------+
多表连接问题 考虑查出所有学生的课程的记录 select * from student
left join student_course on student.id = student_course.sid
left join course on student_course.cid = course.id; +----+--------+------+------+------+--------+------+
| id | name | sid | cid | id | cname | tid |
+----+--------+------+------+------+--------+------+
| | 张三 | | | | 数学 | |
| | 李四 | | | | 数学 | |
| | 张三 | | | | 英语 | |
| | 张三 | | | | 语文 | |
| | 李四 | | | | 体育 | |
| | 初一 | | | | 体育 | |
| | 王二 | | | | 物理 | NULL |
| | 王二 | | | NULL | NULL | NULL |
| | 初二 | NULL | NULL | NULL | NULL | NULL |
+----+--------+------+------+------+--------+------+
用学生表连接中间表,再连接课程表可以得到结果。连接操作是针对两个表之间的,所以上面的结果是从左到右,两两连接得到的。
如果你有更多关于连接的问题,或者发现文章中的错误,欢迎留言交流
参考资料
《数据库系统概念》
03--SQLtie三言两语SQLtie链接(join)的更多相关文章
- 2018.03.27 python pandas merge join 使用
#2.16 合并 merge-join import numpy as np import pandas as pd df1 = pd.DataFrame({'key1':['k0','k1','k2 ...
- 数据库 的几种链接 join
直接demo,懒的同学可以看看效果 两个表的数据 join和inner join一样 full join报错,可有大神知道原因?
- 十几张表的join(千万级/百万级表) 7hours-->5mins
================START============================== 来了一个mail说是job跑得很慢,调查下原因 先来看下sql: SELECT h.order_ ...
- sort merge join导致temp被爆菊
SQL_ID cqsz37256v36j, child number 1 ------------------------------------- INSERT /*+append*/ INTO T ...
- oracle相关的知识
01.表空间的创建与删除 Spool 目录 (把sql语句都记录在txt文件中)spool e:\xxx.txtSpool off 结束 SQL> --清除屏幕信息SQL> cle ...
- 013:Rank、视图、触发器、MySQL内建函数
一. Rank 给出不同的用户的分数,然后根据分数计算排名 (gcdb@localhost) 09:34:47 [mytest]> create table t_rank(id int,scor ...
- 20170621_oracle练习
========================= 启动Oracle ========================= --->启动OracleOraDb11g_home1TNSListene ...
- .Netcore 2.0 Ocelot Api网关教程(4)- 服务发现
本文介绍Ocelot中的服务发现(Service Discovery),Ocelot允许指定一个服务发现提供器,之后将从中寻找下游服务的host和port来进行请求路由.关于服务发现的详细介绍请点击. ...
- sql monitor生成不了报告& FFS hint不生效两个问题思考
事情的发生就是这么偶然,一步步的深入才能汲取到更深入的知识~~ -------------------START------------------------------------------- ...
随机推荐
- vue 项目部署到nginx
第一步在控制台终端输入npm run build 打包完成之后项目中会生成一个dist文件夹,直接访问里面的index.html就ok了 第二步配置nginx 第三步重启nginx service n ...
- CSS定位相关
CSS display:inline和float:left两者区别 ①display:inline:任何不是块级元素的可见元素都是内联元素.其表现的特性是“行布局”形式!(行布局:其表现形式始终以行进 ...
- GOF23设计模式之适配器模式
GOF23设计模式之适配器模式 结构型模式: 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题. 分类:适配器模式.代理模式.桥接模式.装饰模式.组合模式.外观模式. ...
- VirtualBox虚拟机下 解决centos系统无法上网的问题
首先,在VirtualBox中设置网卡连接方式:点“设置”,在弹出的界面中点“网络”,最后选择“连接方式”为“桥接网卡”或者网都可以络地址转换 这两种我试了试都可以 接下来修改一个文件就行: 1.打 ...
- (31)Spring Boot导入XML配置【从零开始学Spring Boot】
[来也匆匆,去也匆匆,在此留下您的脚印吧,转发点赞评论: 您的认可是我最大的动力,感谢您的支持] Spring Boot理念就是零配置编程,但是如果绝对需要使用XML的配置,我们建议您仍旧从一个@Co ...
- 洛谷 P3183 BZOJ 4562 [HAOI2016]食物链
题目描述 如图所示为某生态系统的食物网示意图,据图回答第1小题现在给你n个物种和m条能量流动关系,求其中的食物链条数.物种的名称为从1到n编号M条能量流动关系形如a1 b1a2 b2a3 b3.... ...
- Kafka中文文档学习笔记
文档位置: /Users/baidu/Documents/Data/Interview/机器学习-数据挖掘/Kafka 据说是目前见到的最好的 Kafka 中文文章 . Kafka 是一个消息系统,原 ...
- gcc指定头文件路径及动态链接库路径
gcc指定头文件路径及动态链接库路径 本文详细介绍了linux 下gcc头文件指定方法,以及搜索路径顺序的问题.另外,还总结了,gcc动态链接的方法以及路径指定,同样也讨论了搜索路径的顺序问题.本 ...
- Swift学习——变量var和let常量的用法(一)
Swift中的变量var和let常量 首先介绍一下Swift中的 var 和 let (1)var 是 variable的缩写形式,是变量的意思 ,是可改变的.并非数据类型 比如: 注意每一个语句后面 ...
- FPGA 浮点单元设计
浮点数在内存中的存放格式例如以下: 地址 +0 +1 +2 +3 内容 SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM 这里 S 代表符号位,1是负,0是正 E 偏移1 ...