深入浅出讲解数据库——关系代数
目录
第2章 关系模型
🪶 第15课:关系代数——专门的关系运算(选择、投影)
对应教材:2.4.2 专门的关系运算
🎓 第一部分:专业学术讲解
这是关系代数中最常用、最重要的运算。
1. 专门的关系运算有哪些?
| 运算 | 符号 | 作用 | 操作对象 |
|---|---|---|---|
| 选择 | σ | 选取满足条件的行 | 单个表 |
| 投影 | π | 选取指定的列 | 单个表 |
| 连接 | ⨝ | 把两个表按条件合并 | 两个表 |
| 除 | ÷ | 查找“同时满足一组条件”的数据 | 两个表 |
今天这节课,我们先学选择和投影。
2. 选择(Selection)
选择:从关系(表)中选取满足指定条件的元组(行)。
写法:
σ 条件 (关系名)
例子:
σ 年龄 > 20 (学生)
举例:
| 学号 | 姓名 | 年龄 | 专业 |
|---|---|---|---|
| 001 | 张三 | 20 | 计算机 |
| 002 | 李四 | 21 | 软件工程 |
| 003 | 王五 | 19 | 计算机 |
σ 年龄 > 20 (学生) 的结果:
| 学号 | 姓名 | 年龄 | 专业 |
|---|---|---|---|
| 002 | 李四 | 21 | 软件工程 |
🧸 选择 = 选行,就像在Excel里用筛选功能,只显示符合条件的行。
3. 投影(Projection)
投影:从关系(表)中选取指定的属性(列)。
写法:
π 属性1, 属性2, ... (关系名)
例子:
π 姓名, 专业 (学生)
举例:
| 学号 | 姓名 | 年龄 | 专业 |
|---|---|---|---|
| 001 | 张三 | 20 | 计算机 |
| 002 | 李四 | 21 | 软件工程 |
| 003 | 王五 | 19 | 计算机 |
π 姓名, 专业 (学生) 的结果:
| 姓名 | 专业 |
|---|---|
| 张三 | 计算机 |
| 李四 | 软件工程 |
| 王五 | 计算机 |
🧸 投影 = 选列,就像在Excel里隐藏某些列,只显示你需要的列。
4. 选择和投影的组合
任何东西的设计都是为实际应用所服务,数据库也不例外,在实际情况中,选择和投影几乎是捆绑使用的,例如,三班的语文老师只关注三班的语文成绩,并不关注其他班的成绩,也不关注三班的非语文成绩
选择和投影可以组合使用。先选择,再投影是最常见的操作顺序。
例子:找出年龄>20的学生的姓名和专业
第一步:选择
σ 年龄 > 20 (学生)
得到:
| 学号 | 姓名 | 年龄 | 专业 |
|---|---|---|---|
| 002 | 李四 | 21 | 软件工程 |
第二步:投影
π 姓名, 专业 ( σ 年龄 > 20 (学生) )
得到:
| 姓名 | 专业 |
|---|---|
| 李四 | 软件工程 |
🧸 先选行,再选列——这是最常用的查询模式。
5. 选择的条件写法
| 条件类型 | 写法 | 例子 |
|---|---|---|
| 比较 | >, <, =, ≥, ≤, ≠ | 年龄 > 20 |
| 逻辑与 | ∧(或 AND) | 年龄 > 20 ∧ 专业 = '计算机' |
| 逻辑或 | ∨(或 OR) | 专业 = '计算机' ∨ 专业 = '软件工程' |
| 逻辑非 | ¬(或 NOT) | ¬(年龄 > 20) |
🏠 第二部分:通俗生活化讲解
好的,专业概念先到这里。现在,我们用你完全能懂的方式来理解“选择”和“投影”。
🧸 故事引入:一张完整的成绩单
想象你手里有一张全班同学的成绩单:
| 学号 | 姓名 | 班级 | 语文 | 数学 | 英语 |
|---|---|---|---|---|---|
| 001 | 张小萌 | 3班 | 85 | 92 | 88 |
| 002 | 李小乐 | 3班 | 78 | 95 | 82 |
| 003 | 王小宝 | 4班 | 90 | 88 | 91 |
| 004 | 赵小美 | 4班 | 82 | 79 | 85 |
这张表里有太多信息了。有时候你只想看一部分。
🧸 选择:只看某些“行”
场景一:你想看3班同学的成绩。
你“选择”班级='3班'的行:
| 学号 | 姓名 | 班级 | 语文 | 数学 | 英语 |
|---|---|---|---|---|---|
| 001 | 张小萌 | 3班 | 85 | 92 | 88 |
| 002 | 李小乐 | 3班 | 78 | 95 | 82 |
🧸 选择 = 按条件筛选行。
场景二:你想看数学≥90分的同学。
你“选择”数学≥90的行:
| 学号 | 姓名 | 班级 | 语文 | 数学 | 英语 |
|---|---|---|---|---|---|
| 001 | 张小萌 | 3班 | 85 | 92 | 88 |
| 002 | 李小乐 | 3班 | 78 | 95 | 82 |
选择就是精确地按条件筛选。
🧸 投影:只看某些“列”
场景:你想发一个通知,只需要知道学生的“姓名”和“班级”。
你“投影”出姓名和班级这两列:
| 姓名 | 班级 |
|---|---|
| 张小萌 | 3班 |
| 李小乐 | 3班 |
| 王小宝 | 4班 |
| 赵小美 | 4班 |
🧸 投影 = 按列筛选,只保留你需要的列。
🧸 组合使用:先选行,再选列
场景:你想知道“3班同学的姓名和语文成绩”。
第一步:选择(选行)——选出3班的行
| 学号 | 姓名 | 班级 | 语文 | 数学 | 英语 |
|---|---|---|---|---|---|
| 001 | 张小萌 | 3班 | 85 | 92 | 88 |
| 002 | 李小乐 | 3班 | 78 | 95 | 82 |
第二步:投影(选列)——只保留姓名和语文
| 姓名 | 语文 |
|---|---|
| 张小萌 | 85 |
| 李小乐 | 78 |
🧸 组合使用 = 先筛选行,再筛选列。
🧸 第四部分:本课小结
今天我们学习了选择和投影:
| 运算 | 符号 | 作用 | 生活类比 |
|---|---|---|---|
| 选择 | σ | 选取满足条件的行 | Excel筛选 |
| 投影 | π | 选取指定的列 | Excel隐藏列 |
核心要点:
-
选择 = 选行(横向筛选)
-
投影 = 选列(纵向筛选)
-
两者经常组合使用:先选行,再选列
一句话记住这节课:
选择是选行,投影是选列;先选行再选列,就能得到你想要的数据子集。
🌟 课后一个小问题
还是那张成绩单:
学号 姓名 班级 语文 数学 001 张三 1班 85 90 002 李四 2班 78 88 003 王五 1班 92 85 请用关系代数的表达式写出以下查询:
找出所有1班的学生
只显示所有学生的姓名和数学成绩
找出1班学生的姓名和语文成绩
🪶 第16课:关系代数——专门的关系运算(连接、除)
对应教材:2.4.2 专门的关系运算
🎓 第一部分:专业学术讲解
上节课我们学习了选择(选行)和投影(选列),它们是对单个表的操作。
今天这节课,我们来学习如何把多个表连接起来——这是关系代数中最强大、也最常用的运算。
🧸 各种连接详解
连接分为θ连接,等值连接,自然连接,外连接,其中等值连接是特殊的θ连接,是θ连接中条件为等值时的连接,需要注意的是:若两表中有多个属性相同,等值连接并不需要保证全部的属性都等值,只需要保证你指定的属性相同即可,不是你指定的则无所谓,但是自然连接是全部都需要相等。
自然连接是等值连接的升级变异版,因为自然连接会自动选择两表中相同的属性,进行等值连接,而且在连接之后还会删除重复的行,与实际应用相符,故而最常用,且若两表中有多个属性相同,自然连接是全部都需要相等。
因为连接都涉及到了匹配问题,故而定然存在没有匹配对象的情况,也就是在关系B中没有与关系A中某元组相匹配的元组,此时就涉及到了外连接,正常连接对于这些没有匹配的元组会直接删去,但是某些情况下不能删或者删了会有不好的影响,外连接的作用就是保留这些没有匹配的元组,将其对应属性设置为NULL(空)
好的!这一课我们把所有连接类型一个一个讲透,不跳步。
一、为什么需要连接?
问题:在关系数据库中,数据是分散存储在多张表中的。
-
学生表存学生信息
-
成绩表存成绩信息
-
课程表存课程信息
需求:我们经常需要把多张表的信息合在一起看。比如:
“查询每个学生的姓名和成绩”
这需要把学生表和成绩表连接起来。
解决方案:连接运算。
二、连接的本质
连接 = 笛卡尔积 + 选择
| 步骤 | 做什么 | 结果大小 | ||||
|---|---|---|---|---|---|---|
| 第一步 | 做笛卡尔积(R × S) | R | × | S | 行 | |
| 第二步 | 按条件选择(σ) | ≤ | R | × | S | 行 |
🧸 理解:笛卡尔积把两表所有行两两配对,然后只保留满足条件的配对。
三、准备好例子数据
为了讲清楚各种连接,我们用同一个例子贯穿始终。
表R:学生表
| 学号 | 姓名 |
|---|---|
| 001 | 张三 |
| 002 | 李四 |
| 003 | 王五 |
表S:成绩表
| 学号 | 课程 | 分数 |
|---|---|---|
| 001 | 数学 | 85 |
| 001 | 语文 | 90 |
| 003 | 数学 | 78 |
注意:
-
张三(001)有两门成绩
-
李四(002)没有成绩
-
王五(003)有一门成绩
四、θ连接(Theta Join)
定义
在笛卡尔积上做条件选择,条件可以是任何比较运算(>、<、=、≠、≥、≤)。
写法
R ⨝ S θ
其中θ是条件表达式。
例子
例子1:等值条件(就是比较运算符是‘=’)
R ⨝ S R.学号 = S.学号
先做笛卡尔积(3行 × 3行 = 9行):
| R.学号 | 姓名 | S.学号 | 课程 | 分数 |
|---|---|---|---|---|
| 001 | 张三 | 001 | 数学 | 85 |
| 001 | 张三 | 001 | 语文 | 90 |
| 001 | 张三 | 003 | 数学 | 78 |
| 002 | 李四 | 001 | 数学 | 85 |
| 002 | 李四 | 001 | 语文 | 90 |
| 002 | 李四 | 003 | 数学 | 78 |
| 003 | 王五 | 001 | 数学 | 85 |
| 003 | 王五 | 001 | 语文 | 90 |
| 003 | 王五 | 003 | 数学 | 78 |
再选择 R.学号 = S.学号:
| R.学号 | 姓名 | S.学号 | 课程 | 分数 |
|---|---|---|---|---|
| 001 | 张三 | 001 | 数学 | 85 |
| 001 | 张三 | 001 | 语文 | 90 |
| 003 | 王五 | 003 | 数学 | 78 |
例子2:非等值条件
R ⨝ S R.学号 < S.学号
从9行笛卡尔积中,选出 R.学号 < S.学号 的行:
| R.学号 | 姓名 | S.学号 | 课程 | 分数 |
|---|---|---|---|---|
| 001 | 张三 | 003 | 数学 | 78 |
| 002 | 李四 | 003 | 数学 | 78 |
🧸 条件不一定是等号,可以是大于、小于、不等于等。
五、等值连接(Equi Join)
定义
θ条件为“=”的连接。
写法
R ⨝ S R.学号 = S.学号
例子
结果和上面等值条件的θ连接一样:
| R.学号 | 姓名 | S.学号 | 课程 | 分数 |
|---|---|---|---|---|
| 001 | 张三 | 001 | 数学 | 85 |
| 001 | 张三 | 001 | 语文 | 90 |
| 003 | 王五 | 003 | 数学 | 78 |
🧸 等值连接是θ连接的特例,只是条件固定为“=”。
六、自然连接(Natural Join)⭐
定义
在等值连接的基础上,自动去掉重复的列。
规则
-
自动寻找两个表中同名且同类型的列
-
以这些列相等为连接条件
-
结果中只保留一份这些同名列
写法
R ⨝ S
(不需要写条件,系统自动找)
例子
R和S都有“学号”列,且类型相同。自然连接自动按 R.学号 = S.学号 连接,并只保留一个学号列:
| 学号 | 姓名 | 课程 | 分数 |
|---|---|---|---|
| 001 | 张三 | 数学 | 85 |
| 001 | 张三 | 语文 | 90 |
| 003 | 王五 | 数学 | 78 |
对比等值连接
| 等值连接 | 自然连接 | |
|---|---|---|
| 学号列 | 出现两次(R.学号, S.学号) | 出现一次 |
| 连接条件 | 必须显式写出 | 自动寻找 |
| 结果 | 可能有重复列 | 无重复列 |
🧸 自然连接是最常用的连接,因为它简洁且不产生冗余列。
七、外连接(Outer Join)
问题引出
在自然连接中,李四(002)没有成绩,所以被丢掉了。
| 学号 | 姓名 | 课程 | 分数 |
|---|---|---|---|
| 001 | 张三 | 数学 | 85 |
| 001 | 张三 | 语文 | 90 |
| 003 | 王五 | 数学 | 78 |
| ~~002~~ | ~~李四~~ | ~~被丢掉了~~ |
外连接:保留不匹配的元组,缺失的值用NULL填充。
7.1 左外连接(Left Outer Join)
定义:保留左表的所有元组。
符号:⟕
写法:R ⟕ S
例子:学生表在左,成绩表在右
| 学号 | 姓名 | 课程 | 分数 | |
|---|---|---|---|---|
| 001 | 张三 | 数学 | 85 | |
| 001 | 张三 | 语文 | 90 | |
| 002 | 李四 | NULL | NULL | ← 李四没有成绩,填空NULL |
| 003 | 王五 | 数学 | 78 |
🧸 左外连接 = 左表全部保留 + 右表能匹配就匹配,不能匹配就填NULL
7.2 右外连接(Right Outer Join)
定义:保留右表的所有元组。
符号:⟖
写法:R ⟖ S
例子:
| 学号 | 姓名 | 课程 | 分数 |
|---|---|---|---|
| 001 | 张三 | 数学 | 85 |
| 001 | 张三 | 语文 | 90 |
| 003 | 王五 | 数学 | 78 |
咦,看起来和自然连接一样?因为右表(成绩表)的所有学号(001、001、003)在左表中都有匹配。如果右表有学号在左表不存在,就会填空NULL。
🧸 右外连接 = 右表全部保留 + 左表能匹配就匹配,不能匹配就填NULL
7.3 全外连接(Full Outer Join)
定义:保留两个表的所有元组。
符号:⟗
写法:R ⟗ S
例子:
| 学号 | 姓名 | 课程 | 分数 |
|---|---|---|---|
| 001 | 张三 | 数学 | 85 |
| 001 | 张三 | 语文 | 90 |
| 002 | 李四 | NULL | NULL |
| 003 | 王五 | 数学 | 78 |
🧸 全外连接 = 左表全部保留 + 右表全部保留,不能匹配的填NULL
外连接对比表
| 类型 | 保留左表 | 保留右表 | 不匹配的处理 |
|---|---|---|---|
| 左外连接 | ✅ 全部 | ❌ 只保留匹配的 | 右表填NULL |
| 右外连接 | ❌ 只保留匹配的 | ✅ 全部 | 左表填NULL |
| 全外连接 | ✅ 全部 | ✅ 全部 | 两边都填NULL |
八、各种连接的结果对比
用同一个例子,把所有连接的结果放在一起对比:
R(学生表):001张三、002李四、003王五
S(成绩表):(001,数学,85)、(001,语文,90)、(003,数学,78)
| 连接类型 | 学号 | 姓名 | 课程 | 分数 | 说明 |
|---|---|---|---|---|---|
| θ连接(=) | 001 | 张三 | 数学 | 85 | 有R.学号和S.学号两列 |
| 001 | 张三 | 语文 | 90 | ||
| 003 | 王五 | 数学 | 78 | ||
| 自然连接 | 001 | 张三 | 数学 | 85 | 去掉重复学号列 |
| 001 | 张三 | 语文 | 90 | ||
| 003 | 王五 | 数学 | 78 | ||
| 左外连接 | 001 | 张三 | 数学 | 85 | 保留李四 |
| 001 | 张三 | 语文 | 90 | ||
| 002 | 李四 | NULL | NULL | ||
| 003 | 王五 | 数学 | 78 | ||
| 右外连接 | 001 | 张三 | 数学 | 85 | 右表全保留 |
| 001 | 张三 | 语文 | 90 | ||
| 003 | 王五 | 数学 | 78 | ||
| 全外连接 | 001 | 张三 | 数学 | 85 | 两表全保留 |
| 001 | 张三 | 语文 | 90 | ||
| 002 | 李四 | NULL | NULL | ||
| 003 | 王五 | 数学 | 78 |
🧸 注意:这个例子中右外连接和自然连接结果相同,是因为右表的所有学号都在左表中有匹配。
九、什么时候用哪种连接?
| 场景 | 推荐连接 | 原因 |
|---|---|---|
| 只需要匹配的数据 | 自然连接 | 简洁,无冗余 |
| 需要保留左表所有数据 | 左外连接 | 例如:查所有学生,没有成绩也要显示 |
| 需要保留右表所有数据 | 右外连接 | 例如:查所有课程,没有被选的也要显示 |
| 需要保留两表所有数据 | 全外连接 | 例如:对比两个表的差异 |
| 需要非等值条件 | θ连接 | 例如:分数比自己高的同学 |
| 只需要相等条件,不关心去重 | 等值连接 | 需要保留两边的学号列时 |
🧸 多表连接详解
学到这我想到了一个问题,实际情况下,表的连接肯定不会只涉及到两个表,但是ds却说连接和除都是对两个表进行的操作,故而我单独问了一下ds,答案是连接和除确实是对两个表进行的操作,对于多个表的连接,是通过多次连接得到的,比如有A,B,C三个表,我们先连接AB,得到一个临时表,再把这个临时表和C连接,此时就完成了多表连接操作
一、直接回答
连接不仅限于两个表,多个表也可以连接。
事实上,在实际的数据库查询中,连接3个、4个甚至更多个表是非常常见的操作。
二、多表连接的原理
核心思想
连接是二元运算,一次只连接两个表。连接多个表时,是多次连接的结果。
执行过程
((R ⨝ S) ⨝ T) ⨝ U ...
步骤:
-
先连接R和S,得到中间结果RS
-
再把RS和T连接,得到RST
-
再把RST和U连接……
-
直到所有表都连接完成
🧸 理解:就像加法,一次只能加两个数,但可以连续加很多次。
三、具体例子
假设有四张表:
学生表(S)
| 学号 | 姓名 |
|---|---|
| 001 | 张三 |
| 002 | 李四 |
选课表(SC)
| 学号 | 课程号 | 成绩 |
|---|---|---|
| 001 | C01 | 85 |
| 001 | C02 | 90 |
| 002 | C01 | 78 |
课程表(C)
| 课程号 | 课程名 |
|---|---|
| C01 | 数据库 |
| C02 | 操作系统 |
教师表(T)
| 课程号 | 教师名 |
|---|---|
| C01 | 王老师 |
| C02 | 李老师 |
需求:查询每个学生的姓名、课程名、成绩、任课教师
这需要连接4张表!
执行过程:
第一步:连接学生表和选课表
S ⨝ SC
结果(临时表1):
| 学号 | 姓名 | 课程号 | 成绩 |
|---|---|---|---|
| 001 | 张三 | C01 | 85 |
| 001 | 张三 | C02 | 90 |
| 002 | 李四 | C01 | 78 |
第二步:连接临时表1和课程表
(S ⨝ SC) ⨝ C
结果(临时表2):
| 学号 | 姓名 | 课程号 | 成绩 | 课程名 |
|---|---|---|---|---|
| 001 | 张三 | C01 | 85 | 数据库 |
| 001 | 张三 | C02 | 90 | 操作系统 |
| 002 | 李四 | C01 | 78 | 数据库 |
第三步:连接临时表2和教师表
((S ⨝ SC) ⨝ C) ⨝ T
最终结果:
| 学号 | 姓名 | 课程号 | 成绩 | 课程名 | 教师名 |
|---|---|---|---|---|---|
| 001 | 张三 | C01 | 85 | 数据库 | 王老师 |
| 001 | 张三 | C02 | 90 | 操作系统 | 李老师 |
| 002 | 李四 | C01 | 78 | 数据库 | 王老师 |
四、多表连接的写法
关系代数写法
π 姓名, 课程名, 成绩, 教师名 (
((S ⨝ SC) ⨝ C) ⨝ T
)
SQL写法(实际使用的语言)
SELECT S.姓名, C.课程名, SC.成绩, T.教师名 FROM 学生表 S JOIN 选课表 SC ON S.学号 = SC.学号 JOIN 课程表 C ON SC.课程号 = C.课程号 JOIN 教师表 T ON C.课程号 = T.课程号
🧸 注意:SQL中的JOIN默认是自然连接/等值连接的效果。
五、多表连接的顺序
问题:连接的顺序重要吗?
答案:逻辑上不重要(结果相同),但性能上很重要。
例子
连接三张表:A ⨝ B ⨝ C
顺序1:(A ⨝ B) ⨝ C
顺序2:(A ⨝ C) ⨝ B
顺序3:(B ⨝ C) ⨝ A
逻辑上:结果相同(只要连接条件正确)
性能上:中间结果的大小不同
| 顺序 | 中间结果大小 | 可能的问题 |
|---|---|---|
| 先连接小表 | 小 | 快 |
| 先连接大表 | 大 | 慢 |
🧸 优化原则:先连接能产生较小结果集的表对。
六、多表连接的几种模式
1. 链式连接(最常见)
表与表之间像链条一样连接:
A ── B ── C ── D
例子:学生 → 选课 → 课程 → 教师
每个表与相邻的表有连接条件。
2. 星型连接(数据仓库常见)
一个中心表连接多个外围表:
B
\
\
A ────── C
/
/
D
例子:销售记录表(事实表)连接 产品表、时间表、门店表、客户表
3. 多路连接
多个表同时连接,条件比较复杂:
A ⨝ B ⨝ C 条件:A.x = B.x AND B.y = C.y AND A.z = C.z
形成循环连接。
本课小结
| 知识点 | 核心内容 |
|---|---|
| 多表连接 | 连接是二元运算,多表连接是多次连接 |
| 连接顺序 | 逻辑上结果相同,性能上不同 |
| 链式连接 | 最常见,表与表像链条一样连接 |
| 星型连接 | 数据仓库中常见,一个中心表连接多个外围表 |
| 优化原则 | 先连接能产生较小结果集的表 |
一句话记住这节课:
多表连接就是多次二元连接,先连两个表,再把结果连下一个表,以此类推;连接的顺序影响性能,但不影响最终结果。
🌟 课后一个小问题
有四张表:
订单表(订单号,客户号,订单日期)
客户表(客户号,客户名,城市)
订单明细表(订单号,商品号,数量)
商品表(商品号,商品名,单价)
如果要查询“每个订单的客户名、订单日期、商品名、数量、总价(数量×单价)”,需要连接哪几张表?连接顺序应该是怎样的?
🧸 除运算详解
除运算比较难理解,一开始ds是和连接一起讲的,但是连接和除的知识点太多了,ds就会讲的很简略,后来我让ds分开讲解连接和除,两者大概的意思明白的差不多了,我的理解:除也是匹配,但是和正常匹配不太一样,除着重于“全部”这个词语,对于两个表,假设为表A和表B,表A÷表B,结果返回A中与B全部匹配的值,这有几个需要注意的点:
①:A具体是和B中的什么进行匹配?
要想匹配,肯定是对于相同的属性进行操作,相同属性具体来说就是AB的公共属性,A匹配的对象就是B中和A公共的属性下的全部元组(B中和A公共的属性下的全部行),B中公共属性下的全部行都需要匹配到才可
具体例子:
例子1:基础版——选修了所有课程的学生
A(选课表)
| 学号 | 课程 |
|---|---|
| 001 | 数学 |
| 001 | 语文 |
| 001 | 英语 |
| 002 | 数学 |
| 002 | 英语 |
| 003 | 数学 |
B(课程表)
| 课程 |
|---|
| 数学 |
| 语文 |
| 英语 |
AB的公共属性是课程,B课程属性下全部行为数学,语文,英语
在A中找与这些行全部匹配的东西,最终找到是:
| 学号 |
|---|
| 001 |
这便是A÷B的结果,相信你也注意到了,这个结果只保留了学号这一属性,并没有保留课程,因为:A ÷ B 的结果只保留 A 中【不属于 B】的那些属性(即非公共属性)。
例子2:带多个公共属性
R(选课成绩表)
| 学号 | 课程 | 学期 |
|---|---|---|
| 001 | 数学 | 2024秋 |
| 001 | 语文 | 2024秋 |
| 001 | 英语 | 2024秋 |
| 002 | 数学 | 2024秋 |
| 002 | 英语 | 2024秋 |
| 003 | 数学 | 2024秋 |
| 001 | 数学 | 2025春 |
| 001 | 语文 | 2025春 |
S(指定条件)
| 课程 | 学期 |
|---|---|
| 数学 | 2024秋 |
| 语文 | 2024秋 |
结果:
| 学号 |
|---|
| 001 |
②:怎么进行匹配?(具体操作步骤是什么?)
步骤1:确定R和S的公共属性(连接属性)
步骤2:计算S在公共属性上的投影(S中所有可能的值)
步骤3:对R中每个候选元组,检查它是否与S的所有值都有配对
步骤4:只保留满足条件的元组
③:最后输出的是什么?
A ÷ B 的结果只保留 A 中【不属于 B】的那些属性(即非公共属性)
④这些公共属性是自动全部匹配吗?还是说可以根据实际情况部分匹配。
我学完除运算后最疑惑的问题就是这个,我问了ds之后得到了答案:公共属性是全部都自动进行匹配(类似于自然连接),此时我又有了一个新的疑问,在实际情况中,对于有多个公共属性的关系来说,我们的查询可能只看某个公共属性,而不关心全部的公共属性,那这个除就有点死板了,我问了ds,ds回答我:
在实际应用中,确实有指定部分属性做“全部”查询的需求。
除运算的“自动找所有公共属性”是数学定义,但现实中我们经常需要自己指定要匹配哪些属性。
一、问题的本质
除运算的数学定义要求:所有公共属性都要匹配。
但现实需求往往是:我只关心某几个属性是否“全部”满足,其他属性我不关心。
| 数学除运算 | 现实需求 |
|---|---|
| 自动找所有公共属性 | 用户指定要匹配的属性 |
| 要求所有公共属性都匹配 | 只要求指定的属性匹配 |
| 不能灵活指定 | 需要灵活指定 |
🧸 结论:数学除运算是基础,实际使用时需要“增强版”——带投影的除运算。
二、具体例子:为什么需要自己指定?
例子:查询“选修了所有数学课的学生”
R(选课表)
| 学号 | 课程 | 学期 | 成绩 |
|---|---|---|---|
| 001 | 微积分 | 2024春 | 85 |
| 001 | 线性代数 | 2024秋 | 90 |
| 001 | 概率论 | 2025春 | 88 |
| 002 | 微积分 | 2024秋 | 78 |
| 002 | 线性代数 | 2024秋 | 82 |
| 003 | 微积分 | 2024秋 | 92 |
S(数学课程表)
| 课程 |
|---|
| 微积分 |
| 线性代数 |
| 概率论 |
如果用数学除运算(自动找所有公共属性)
公共属性 = {课程}(R和S都有“课程”)
R ÷ S 的结果:
| 学号 |
|---|
| 001 |
没问题,结果正确。
但如果S中有“学期”呢?
S(数学课程表,带学期要求)
| 课程 | 学期 |
|---|---|
| 微积分 | 2024秋 |
| 线性代数 | 2024秋 |
数学除运算:公共属性 = {课程, 学期}
R ÷ S 的结果:
为空
三、解决方案:投影 + 除运算
步骤:先把R投影到我们关心的属性上,再做除运算。
需求:查询“选修了微积分和线性代数这两门课的学生”(忽略学期)
第一步:把R投影到(学号,课程)上
π 学号, 课程 (R)
| 学号 | 课程 |
|---|---|
| 001 | 微积分 |
| 001 | 线性代数 |
| 001 | 概率论 |
| 002 | 微积分 |
| 002 | 线性代数 |
| 003 | 微积分 |
第二步:用投影后的R做除运算
π 学号, 课程 (R) ÷ S
| 学号 |
|---|
| 001 |
| 002 |
🧸 结果:001和002都选修了微积分和线性代数(不管在哪个学期)。
四、通用模式:带投影的除运算
需求:查询“在属性集X上,满足S中所有条件的元组”
公式:
π ( R ) ÷ S X
其中X是你关心的属性集合。
| 步骤 | 操作 | 作用 |
|---|---|---|
| 1 | 投影 π_X (R) | 只保留你关心的属性 |
| 2 | 除运算 ÷ S | 在投影结果上做“全部”查询 |
🧸 这就是现实中的做法:先投影,再除。
五、对比:数学除 vs 现实除
| 对比项 | 数学除运算 | 现实中的做法 |
|---|---|---|
| 公共属性 | 自动找所有 | 用户指定(通过先投影) |
| 匹配要求 | 所有公共属性 | 用户指定的那些 |
| 灵活性 | 低 | 高 |
现实中的SQL实现(没有直接的除,用其他方式):
-- 查询选修了微积分和线性代数的学生
SELECT 学号
FROM 选课表
WHERE 课程 IN ('微积分', '线性代数')
GROUP BY 学号
HAVING COUNT(DISTINCT 课程) = 2
🧸 这里就是自己指定了要匹配的属性:课程(忽略学期)。
七、总结
| 问题 | 答案 |
|---|---|
| 数学除运算是自动找公共属性吗? | 是的。自动找R和S的所有同名属性 |
| 现实中能自己指定吗? | 能。通过“先投影,再除”实现 |
| 为什么需要自己指定? | 因为实际需求往往只关心部分属性,不关心其他属性 |
| 怎么做? | π 关心的属性 (R) ÷ π 关心的属性 (S) |
🧸 核心:数学除运算是理论基础,实际使用时可以灵活组合投影和除运算来实现“指定部分属性”的需求。
通过这个我们可以发现,选择,投影,连接,除,这四个专门的关系运算以及之前学的传统运算都很重要,在实际情况中还会涉及他们的搭配使用。
一、除运算是什么?
定义
除运算:R ÷ S 的结果是满足以下条件的元组:在R中,它与S中的每一个元组都有配对。
通俗理解
除运算 = “全部”查询
-
查询“选修了所有课程的学生”
-
查询“购买了所有商品的顾客”
-
查询“参加了全部社团活动的同学”
符号
R ÷ S
二、除运算的本质
数学定义
R ÷ S = { t | t ∈ π (R) ∧ ∀ s ∈ S ( (t,s) ∈ R ) }
属性集
我在用ds学数据库的同时也在看数上讲的,书上一堆奇奇怪怪的符号,对于初学者根本看不懂也根本看不下去。。。
三个关键点
| 关键点 | 说明 |
|---|---|
| t | R中除去S的属性后的元组 |
| ∀ s ∈ S | 对于S中的每一个元组 |
| (t,s) ∈ R | (t,s)这个组合在R中存在 |
一句话
找出R中那些与S中所有元组都配对过的元组。
三、除运算的步骤
标准步骤(4步法)
步骤1:确定R和S的公共属性(连接属性)
步骤2:计算S在公共属性上的投影(S中所有可能的值)
步骤3:对R中每个候选元组,检查它是否与S的所有值都有配对
步骤4:只保留满足条件的元组
四、具体例子(由简到难)
例子1:基础版——选修了所有课程的学生
R(选课表)
| 学号 | 课程 |
|---|---|
| 001 | 数学 |
| 001 | 语文 |
| 001 | 英语 |
| 002 | 数学 |
| 002 | 英语 |
| 003 | 数学 |
S(课程表)
| 课程 |
|---|
| 数学 |
| 语文 |
| 英语 |
执行步骤:
步骤1:公共属性是“课程”
步骤2:S在“课程”上的值 = {数学, 语文, 英语}
步骤3:检查每个学生:
| 学号 | 选修的课程 | 是否包含{数学,语文,英语}? |
|---|---|---|
| 001 | {数学,语文,英语} | ✅ 是 |
| 002 | {数学,英语} | ❌ 否(缺语文) |
| 003 | {数学} | ❌ 否(缺语文、英语) |
步骤4:结果
| 学号 |
|---|
| 001 |
R ÷ S = {001}
🧸 解释:只有001选修了S中的所有课程。
例子2:带多个公共属性
R(选课成绩表)
| 学号 | 课程 | 学期 |
|---|---|---|
| 001 | 数学 | 2024秋 |
| 001 | 语文 | 2024秋 |
| 001 | 英语 | 2024秋 |
| 002 | 数学 | 2024秋 |
| 002 | 英语 | 2024秋 |
| 003 | 数学 | 2024秋 |
| 001 | 数学 | 2025春 |
| 001 | 语文 | 2025春 |
S(指定条件)
| 课程 | 学期 |
|---|---|
| 数学 | 2024秋 |
| 语文 | 2024秋 |
执行步骤:
步骤1:公共属性是(课程,学期)——两个属性!
步骤2:S中的组合 = {(数学,2024秋), (语文,2024秋)}
步骤3:检查每个学生:
| 学号 | 在R中的(课程,学期)组合 | 是否包含S的所有组合? |
|---|---|---|
| 001 | {(数学,2024秋),(语文,2024秋),(英语,2024秋),(数学,2025春),(语文,2025春)} | ✅ 是 |
| 002 | {(数学,2024秋),(英语,2024秋)} | ❌ 否(缺语文,2024秋) |
| 003 | {(数学,2024秋)} | ❌ 否(缺语文,2024秋) |
步骤4:结果
| 学号 |
|---|
| 001 |
🧸 解释:公共属性可以是多个列的组合。S中有几行,每个学生就必须有几行配对。
例子3:S只有一行
R(选课表)
| 学号 | 课程 |
|---|---|
| 001 | 数学 |
| 001 | 语文 |
| 002 | 数学 |
| 003 | 数学 |
S(指定课程)
| 课程 |
|---|
| 数学 |
R ÷ S:
| 学号 |
|---|
| 001 |
| 002 |
| 003 |
🧸 解释:当S只有一行时,除运算等价于投影 + 去重——找出所有选修了数学的学生。
例子4:S为空
R(选课表)
| 学号 | 课程 |
|---|---|
| 001 | 数学 |
| 002 | 数学 |
S(空表,没有行)
R ÷ S:
| 学号 |
|---|
| 001 |
| 002 |
🧸 解释:S为空时,条件“与S中每一个元组都配对”是空真(没有任何限制),所以返回R中所有候选元组。
五、除运算 vs 其他运算
| 运算 | 作用 | 例子 |
|---|---|---|
| 选择(σ) | 按条件筛选行 | 找出成绩≥90的学生 |
| 投影(π) | 按列筛选 | 只看学号和姓名 |
| 连接(⨝) | 把两个表合并 | 把学生表和成绩表合并 |
| 除(÷) | 找“全部” | 找出选修了所有课程的学生 |
关键区别
-
连接:找“有”配对
-
除:找“有所有”配对
🧸 连接问的是:“这个学生选了数学吗?”(存在性)
除问的是:“这个学生选了所有课程吗?”(全体性)
六、除运算的常见应用场景
| 场景 | R是什么 | S是什么 | 结果 |
|---|---|---|---|
| 选修了所有课程的学生 | 选课表(学号,课程) | 课程表(课程) | 学号 |
| 购买了全部商品的顾客 | 购买记录(顾客ID,商品ID) | 商品表(商品ID) | 顾客ID |
| 参加了所有活动的员工 | 参与记录(员工ID,活动ID) | 活动表(活动ID) | 员工ID |
| 在所有部门都工作过的员工 | 工作记录(员工ID,部门ID) | 部门表(部门ID) | 员工ID |
七、除运算的SQL实现
标准的SQL没有直接的“除”运算,但可以用其他方式实现:
方法1:GROUP BY + HAVING
sql
SELECT 学号
FROM 选课表
WHERE 课程 IN ('数学', '语文', '英语')
GROUP BY 学号
HAVING COUNT(DISTINCT 课程) = 3
方法2:NOT EXISTS双重否定
sql
SELECT DISTINCT 学号
FROM 选课表 R1
WHERE NOT EXISTS (
SELECT 课程 FROM 课程表 S
WHERE NOT EXISTS (
SELECT * FROM 选课表 R2
WHERE R2.学号 = R1.学号
AND R2.课程 = S.课程
)
)
🧸 理解:没有一门课程是这个学生没选的 = 选了所有课程。
九、常见易错点
| 易错点 | 正确理解 |
|---|---|
| 搞混除和连接 | 连接找“有配对”,除找“有所有配对” |
| 忽略公共属性 | 公共属性可能是多个列的组合 |
| 忘记去重 | 结果中不会有重复元组 |
| S为空时结果为空 | 不对!S为空时,结果是R中所有候选元组 |
十、本课小结
| 知识点 | 核心内容 |
|---|---|
| 除运算的定义 | 找出与S中每一个元组都有配对的R中的元组 |
| 核心应用 | “全部”查询:选了所有课、买了所有商品…… |
| 执行步骤 | 4步法:找公共属性 → 找S的值集 → 检查每个候选 → 输出 |
| 与连接的区别 | 连接是“存在”,除是“全部” |
一句话记住这节课:
除运算是关系代数中的“全部”查询——找出那些与S中每一个元组都有配对的元组,就像找“选修了所有课程的学生”。
🌟 课后小问题
有两个表:
R(仓库库存表)
仓库号 商品号 W01 P01 W01 P02 W01 P03 W02 P01 W02 P02 W03 P01 S(商品清单)
商品号 P01 P02 P03 问:R ÷ S 的结果是什么?它表示什么含义?
更多推荐


所有评论(0)