数据库关系代数(习题)
本文系统阐述了关系代数应用题的解题方法,包括基本运算(选择、投影、连接等)和扩展操作(除运算、半连接等)。文章详细分析了题目构成要素、常见题型分类,并提供了分步解题策略:需求分析→运算符选择→表达式优化。通过典型例题(如多表查询、分组聚合、复杂条件筛选)展示了具体解法,特别强调连接运算的选择依据和半连接的优化价值。在分布式数据库场景中,半连接能显著减少数据传输量。文章总结出运算选择决策树,帮助读者
一、应用题内容形式
关系代数应用题通常要求使用关系代数表达式解决实际查询问题,涉及以下操作:
-
基本操作:选择(σ)、投影(π)、并(∪)、差(−)、笛卡尔积(×)
-
扩展操作:连接(⋈)、自然连接(⋈)、重命名(ρ)、除(÷)
-
常见场景:
-
多表关联查询
-
嵌套条件查询(如“查询选修所有课程的学生”)
-
集合运算(如并集、差集)
-
聚合与分组(需结合扩展操作)
-
二、解题步骤
-
明确查询目标
确定需要输出的属性(投影操作)。 -
分析涉及的关系表
列出所有需要使用的表。 -
构建表间关联
使用连接(⋈) 或 自然连接(⋈) 关联表(常用连接条件:外键 = 主键)。 -
添加过滤条件
使用选择(σ) 筛选满足条件的元组。 -
处理复杂逻辑
-
嵌套查询 → 使用 除(÷) 或 差(−)
-
“所有”型查询 → 用 除运算(÷)
-
“不存在”型查询 → 用 差运算(−)
-
-
优化表达式
合并操作、调整顺序(先选择后投影,减少中间结果大小)。
三、数据库关系代数应用题的内容形式
(一)题目构成要素
- 关系模式定义
给出具体数据库的关系模式,包括关系名、属性列表及主键(用下划线标注)。
例:
学生表:Student(Sno, Sname, Ssex, Sage, Sdept)(Sno 为主键)
课程表:Course(Cno, Cname, Cpno, Ccredit)(Cno 为主键)
选课表:SC(Sno, Cno, Grade)(Sno+Cno 为主键)
- 具体查询需求
以自然语言描述数据查询或操作需求,涉及选择、投影、连接、除等关系代数运算。
例:
"查询选修了 ' 数据库原理 ' 课程且成绩在 80 分以上的学生姓名"
"计算各系学生的平均年龄"
(二)常见题型分类
- 基本运算题:单一使用选择(σ)、投影(π)、并(∪)、差(-)等运算
- 连接运算题:涉及自然连接(⋈)、等值连接(▷◁)、外连接(⟕/⟖)等
- 复杂组合题:综合使用多种运算(如先连接再选择,或结合除运算)
- 聚合运算题:包含分组(γ)和聚集函数(如 COUNT、AVG)
四、关系代数应用题具体解法步骤
(一)需求分析(关键步骤)
- 确定参与运算的关系:明确需要从哪些表中获取数据
▶ 例:查询学生成绩→涉及 Student 和 SC 表
- 分解查询条件:将自然语言条件拆解为关系代数可表达的逻辑
▶ 例:"性别为女且年龄 > 20"→σ(Ssex=' 女 ' ∧ Sage>20)
- 确定运算顺序:遵循 "先选择 / 投影简化数据,再连接,最后处理复杂条件" 的原则
(二)运算符选择策略
|
需求类型 |
推荐运算符 |
示例(查询计算机系男生) |
|
行过滤 |
选择(σ) |
σ(Sdept=' 计算机系 ' ∧ Ssex=' 男 ') |
|
列筛选 |
投影(π) |
π(Sname, Sage)(Student) |
|
多表关联 |
自然连接(⋈)/ 等值连接 |
Student ⋈ SC (按 Sno 连接) |
|
分组聚合 |
分组(γ)+ 聚集函数 |
γ(Sdept, AVG(Sage))(Student) |
|
全集筛选(如 "所有课程都选修") |
除运算(÷) |
SC ÷ Course (查询选修所有课程的学生) |
(三)表达式优化技巧
- 尽早执行选择运算:减少参与连接的数据量
▶ 错误:Student ⋈ SC → σ(Grade>80)
▶ 正确:σ(Grade>80)(SC) ⋈ Student
- 合理使用投影减少属性:避免处理无关列
- 优先执行等值连接:利用主键 - 外键关系提高效率
五、典型例题及详解
(一)例题背景
设有以下三个关系:
- 学生表 Student(Sno, Sname, Ssex, Sage, Sdept)
(学号,姓名,性别,年龄,所在系)
- 课程表 Course(Cno, Cname, Cpno, Ccredit)
(课程号,课程名,先修课号,学分)
- 选课表 SC(Sno, Cno, Grade)
(学号,课程号,成绩)
(二)具体题目与解答
【题目 1】查询选修了课程号为 'C001' 且成绩高于 85 分的学生姓名和所在系
解答步骤:
- 选择 SC 表中 Cno='C001' 且 Grade>85 的记录:σ(Cno='C001' ∧ Grade>85)(SC)
- 将结果与 Student 表按 Sno 自然连接:Student ⋈ [σ条件(SC)]
- 投影出 Sname 和 Sdept:π(Sname, Sdept)(Student ⋈ σ条件(SC))
关系代数表达式:
π(Sname, Sdept)(Student ⋈ σ(Cno='C001' ∧ Grade>85)(SC))
【题目 2】查询每个学生选修的课程数及平均成绩(结果按平均成绩降序排列)
解答步骤:
- 按 Sno 分组,计算每组课程数(COUNT (Cno))和平均成绩(AVG (Grade)):
γ(Sno, COUNT(Cno)→Cnum, AVG(Grade)→AvgGrade)(SC)
2. 按 AvgGrade 降序排序(注:传统关系代数不直接支持排序,需扩展说明)
关系代数表达式(扩展形式):
γ(Sno, Cnum=COUNT(Cno), AvgGrade=AVG(Grade))(SC) ORDER BY AvgGrade DESC
【题目 3】查询选修了所有计算机系课程的学生姓名
解答步骤:
- 先获取计算机系所有课程的 Cno:π(Cno)(σ(Cdept='计算机系')(Course))
- 用除运算找出在 SC 表中对上述课程集合全选修的学生:SC ÷ π(Cno)(计算机系课程)
- 连接 Student 表获取姓名:Student ⋈ (SC ÷ π(Cno)(σ(Cdept='计算机系')(Course)))
- 投影 Sname:π(Sname)(Student ⋈ (SC ÷ 计算机系课程Cno))
关系代数表达式:
π(Sname)(Student ⋈ (SC ÷ π(Cno)(σ(Cdept='计算机系')(Course))))
(三)结果示例(以题目 1 为例)
假设 SC 表中有记录:
|
Sno |
Cno |
Grade |
|
S001 |
C001 |
90 |
|
S002 |
C001 |
80 |
|
Student 表中有: |
||
|
Sno |
Sname |
Sdept |
|
----- |
------- |
--------- |
|
S001 |
张三 |
信息系 |
|
S002 |
李四 |
计算机系 |
|
运算结果: |
||
|
Sname |
Sdept |
|
|
------- |
------- |
|
|
张三 |
信息系 |
六、解题注意事项
- 运算符优先级:括号 > 选择 / 投影 > 连接 > 并 / 差 > 除
- 属性同名处理:连接后出现重复属性需用别名(如Course ⋈ SC的 Cno 无需别名,因 SC 的 Cno 是外键)
- 除运算条件:被除数关系的属性集需包含除数关系的属性集(如 SC (Sno,Cno) ÷ Course (Cno) 合法)
- 外连接使用场景:当需要保留未匹配元组时(如查询所有学生及其选课情况,包括未选课学生)
通过以上结构化分析,可系统掌握关系代数应用题的解题逻辑,关键在于将自然语言需求逐层拆解为基本运算的组合,并合理优化运算顺序以提高效率。
七、补充例题及详解(覆盖更多运算场景)
(一)外连接运算题
【题目 4】查询所有学生的学号、姓名及选修课程号,包括未选课的学生
解答步骤:
- 由于需要保留未选课学生(Student 中存在但 SC 中无匹配的元组),使用左外连接
- 按 Sno 进行左外连接:Student ⟕ SC
- 投影需要的属性:π(Sno, Sname, Cno)(Student ⟕ SC)
关系代数表达式:
π(Sno, Sname, Cno)(Student ⟕ SC)
结果示例(假设 S003 未选课):
|
Sno |
Sname |
Cno |
|
S001 |
张三 |
C001 |
|
S002 |
李四 |
C001 |
|
S003 |
王五 |
NULL |
(二)差运算与选择组合题
【题目 5】查询没有选修课程号为 'C002' 的学生姓名
解答步骤:
- 找到所有学生的集合:π(Sno, Sname)(Student)
- 找到选修了 C002 的学生集合:π(Sno, Sname)(Student ⋈ σ(Cno='C002')(SC))
- 用差运算得到未选修 C002 的学生:步骤1 - 步骤2
关系代数表达式:
π(Sno, Sname)(Student) - π(Sno, Sname)(Student ⋈ σ(Cno='C002')(SC))
结果示例(假设 S001 选修 C001,S002 选修 C001,C002 无选修记录):
|
Sno |
Sname |
|
S001 |
张三 |
|
S002 |
李四 |
(三)除运算进阶题(多条件筛选)
【题目 6】查询同时选修了课程号 'C001' 和 'C002' 的学生姓名
解答步骤:
- 构建目标课程集合:{('C001'), ('C002')},需先投影 SC 中的 (Sno, Cno)
- 使用除运算前需构造包含 Sno 和 Cno 的关系,除数为目标课程的 Cno 集合
-
- 除数关系:D = π(Cno)(σ(Cno='C001' ∨ Cno='C002')(Course))
-
- 被除数关系:SC_SELECTED = π(Sno, Cno)(SC)
- 除运算筛选同时选修两门课的学生:SC_SELECTED ÷ D
- 连接 Student 表获取姓名:π(Sname)(Student ⋈ (SC_SELECTED ÷ D))
关系代数表达式:
π(Sname)(Student ⋈ (π(Sno, Cno)(SC) ÷ π(Cno)(σ(Cno IN {'C001','C002'}(Course))))
(四)分组聚合与排序题
【题目 7】查询各系学生人数及平均年龄,结果按人数降序、年龄升序排列
解答步骤:
- 按 Sdept 分组,计算 COUNT (Sno) 和 AVG (Sage):
γ(Sdept, StuNum=COUNT(Sno), AvgAge=AVG(Sage))(Student)
- 扩展排序操作(传统关系代数不支持,需显式说明):
ORDER BY StuNum DESC, AvgAge ASC
关系代数表达式(扩展形式):
γ(Sdept, StuNum=COUNT(Sno), AvgAge=AVG(Sage))(Student) ORDER BY StuNum DESC, AvgAge ASC
(五)自连接题(查询先修课信息)
【题目 8】查询每门课程的课程名及其先修课名称
解答步骤:
- 课程表自连接,通过先修课号 Cpno 关联自身:
Course AS C1 ⋈ (C1.Cpno = C2.Cno) Course AS C2
- 投影课程名和先修课名:π(C1.Cname, C2.Cname)
关系代数表达式:
π(C1.Cname, C2.Cname)(Course C1 ⋈ (C1.Cpno = C2.Cno) Course C2)
结果示例(假设 C001 先修课为 C002):
|
Cname |
Cpname |
|
数据库 |
数据结构 |
八、例题设计思路总结
- 覆盖全运算类型:新增外连接(⟕)、差运算(-)、自连接、复杂除运算场景
- 贴近实际业务:
-
- 外连接解决 "保留未匹配数据" 的常见需求
-
- 差运算处理 "排除特定条件" 的筛选
-
- 自连接用于同表属性关联(如先修课查询)
- 强化运算组合:
-
- 除运算结合条件筛选(题目 6 的Cno IN {})
-
- 聚合运算与排序结合(题目 7 的扩展语法)
- 注意命名规范:
-
- 自连接时使用别名(C1/C2)避免属性歧义
-
- 聚合结果显式定义别名(StuNum/AvgAge)
通过以上例题,可进一步掌握关系代数在复杂业务场景中的应用,重点在于:
- 明确运算目标对应的关系代数语义(如外连接的保留策略)
- 合理拆分多条件查询为基本运算的组合
- 注意同名属性的处理(别名 / 投影过滤)
-
九、半连接运算专项例题
(一)半连接定义与适用场景
半连接(⋉)是连接运算的优化形式,定义为:
R ⋉ S = π(R属性)(R ⋈ S)
即仅保留左关系中与右关系匹配的元组,投影左关系属性。
核心优势:在分布式数据库中减少跨节点数据传输,避免处理无关元组。
(二)典型例题:半连接在选课查询中的应用
【题目 9】查询选修了课程号为 'C001' 的学生的学号、姓名和所在系(使用半连接实现)
关系模式(同前):
- Student(Sno, Sname, Ssex, Sage, Sdept)
- SC(Sno, Cno, Grade)
-
解答步骤:
- 筛选目标课程的选课记录:
-
对 SC 表进行选择运算,提取 Cno='C001' 的元组:
σ(Cno='C001')(SC)
- 执行半连接操作:
-
将 Student 表与步骤 1 的结果进行半连接,仅保留 Student 中在 SC 存在匹配的元组:
Student ⋉ σ(Cno='C001')(SC)
(等价于π(Student属性)(Student ⋈ σ(Cno='C001')(SC)))
- 投影目标属性:
-
提取 Sno、Sname、Sdept 列:
π(Sno, Sname, Sdept)(Student ⋉ σ(Cno='C001')(SC))
关系代数表达式:
π(Sno, Sname, Sdept)(Student ⋉ σ(Cno='C001')(SC))
结果示例(假设 SC 中 C001 对应 Sno 为 S001、S003):
Sno
Sname
Sdept
S001
张三
信息系
S003
王五
计算机系
(三)半连接与自然连接的对比
运算类型
结果特征
数据量对比
适用场景
自然连接
包含两表所有匹配列的完整元组
结果属性数 = 左 + 右 - 公共属性
需完整关联数据时
半连接
仅保留左表匹配元组的左表属性
结果属性数 = 左表属性数
只需左表部分属性时(优化查询)
示例对比:
- 自然连接:Student ⋈ σ(Cno='C001')(SC)
-
结果包含 Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
- 半连接:Student ⋉ σ(Cno='C001')(SC)
-
结果仅包含 Sno, Sname, Ssex, Sage, Sdept(过滤掉 SC 的 Cno、Grade)
(四)半连接在多表查询中的扩展应用
【题目 10】查询选修了 “数据库原理” 课程(Cname=' 数据库原理 ')的学生姓名(使用半连接链)
解答步骤:
- 定位目标课程的 Cno:
-
π(Cno)(σ(Cname='数据库原理')(Course))
- 筛选对应的选课记录:
-
SC ⋈ 步骤1(等价于σ(Cno=步骤1结果)(SC))
- 半连接 Student 表获取姓名:
-
Student ⋉ (SC ⋈ π(Cno)(σ(Cname='数据库原理')(Course)))
最终投影:π(Sname)(Student ⋉ (SC ⋈ 课程筛选结果))
关系代数表达式:
π(Sname)(Student ⋉ (SC ⋈ π(Cno)(σ(Cname='数据库原理')(Course))))
优化意义:
通过半连接链,先在 Course 表定位 Cno,再通过 SC 过滤 Student 表,避免 Student 表与 Course 表直接连接产生大量中间数据。
十、半连接运算核心要点总结
- 语法本质:
-
半连接是 “连接后投影左表属性” 的简化表示,数学上等价于π(R)(R ⋈ S)
- 适用场景:
-
- 仅需获取左表中与右表匹配的元组属性
-
- 分布式数据库中减少跨节点传输的数据量(如左表在本地,右表在远端)
- 与除运算的区别:
-
- 半连接:存在至少一个匹配元组即保留左表元组(存在量词)
-
- 除运算:需匹配右表所有元组(全称量词,如题目 3 的 “选修所有课程”)
- 表达式书写:
-
显式标注连接条件(如R ⋉ (S WHERE 条件)),或通过子表达式嵌套实现
通过半连接例题的练习,可掌握关系代数的优化思想 —— 在保证结果正确的前提下,通过运算顺序调整和运算符选择(如用半连接替代全连接),减少中间结果的数据量,提升查询效率。
十一、半连接与其他连接运算的差异对比表
|
运算类型 |
定义核心 |
结果特征 |
保留元组 |
结果属性数 |
典型适用场景 |
|
等值连接 |
R ▷◁ S (A=B):基于属性 A=B 的条件连接两表 |
包含两表所有属性,保留满足 A=B 的元组 |
仅匹配元组 |
左表属性 + 右表属性(可能重复需别名) |
多表关联获取完整数据(如订单与客户信息) |
|
自然连接 |
特殊等值连接,自动去除重复公共属性 |
合并公共属性,仅保留唯一列名的元组 |
仅匹配元组 |
左表属性 + 右表属性 - 公共属性数 |
简洁展示多表关联结果(如学生与选课信息) |
|
左外连接 |
R ⟕ S:保留左表所有元组,右表不匹配元组填 NULL |
包含两表所有属性,左表未匹配元组的右表属性为 NULL |
左表全部 + 右表匹配元组 |
同等值连接 |
需保留左表未关联数据(如查询所有学生及其选课情况) |
|
半连接 |
R ⋉ S = π(R)(R ⋈ S):连接后仅保留左表属性 |
仅包含左表属性,且仅保留左表中与右表匹配的元组 |
左表匹配元组 |
等于左表属性数 |
仅需左表部分属性时的优化查询(如分布式场景数据过滤) |
核心差异说明:
- 元组保留策略:
-
- 半连接与等值 / 自然连接:均仅保留匹配元组,但半连接过滤右表属性
-
- 外连接 vs 半连接:外连接保留左表未匹配元组(填 NULL),半连接仅保留匹配元组的左表属性
- 属性处理:
-
- 半连接是 "投影裁剪" 后的连接,主动丢弃右表属性,适合 "只需要左表数据" 的场景
-
- 等值连接 / 外连接保留所有属性,可能产生冗余数据(如 SC 表的 Grade 在学生查询中无用)
十二、分布式数据库场景下的半连接优化案例
(一)场景描述
假设分布式数据库中:
- 本地节点:存储 Student 表(10 万条记录,本地计算资源有限)
- 远程节点:存储 SC 表和 Course 表(SC 表 50 万条记录,需跨网络访问)
需求:查询选修了 "计算机网络" 课程的学生姓名(仅需返回 Sname)
(二)传统等值连接方案(低效)
- 跨节点操作:
-
- 从远程节点拉取整个 SC 表到本地(50 万条)
-
- 本地节点拉取 Course 表中 Cname=' 计算机网络 ' 的 Cno(假设 1 条)
-
- 执行等值连接:Student ⋈ (SC ⋈ Course)
- 问题:
-
- 传输 50 万条 SC 数据到本地,网络开销大
-
- 本地处理大量无关数据(如 SC 中的 Grade、Course 中的学分等)
(三)半连接优化方案(高效)
步骤拆解:
- 远程节点预处理(仅传输必要键值):
- 本地节点执行半连接:
关系代数表达式:
(四)优化效果对比
|
指标 |
传统方案 |
半连接方案 |
优化幅度 |
|
跨网络传输数据量 |
50 万条 SC 完整记录 |
仅传输 Matched_Sno(假设 1000 条 Sno) |
98%+ 减少 |
|
本地计算复杂度 |
处理 50 万条连接中间结果 |
处理 1000 条匹配 Sno 对应的 Student 记录 |
显著降低 |
|
响应时间 |
高延迟(网络瓶颈) |
低延迟(仅传输关键键值) |
提升 5-10 倍 |
(五)优化原理
- 数据剪枝:
-
- 通过半连接的 "投影左表属性" 特性,提前在远程节点过滤掉 SC 表的 Cno、Grade 等无关列,仅保留 Sno(主键,数据量小)
- 运算下推:
-
- 将选择和投影运算推送到数据所在的远程节点执行,符合分布式查询优化中的 "本地化处理" 原则
- 避免全表扫描:
-
- 本地节点无需存储和处理完整的 SC 表,仅需根据 Sno 索引快速定位 Student 记录
十三、复杂场景下的运算选择决策树
当面临多表查询时,可按以下逻辑选择连接类型:

总结:半连接的核心价值
- 数据精简:通过 "连接 + 投影" 的组合操作,精准过滤无关数据
- 分布式友好:在跨节点查询中显著减少网络传输量,是分布式数据库查询优化的重要手段
- 语义明确:适用于 "存在匹配即可" 的存在量词场景(vs 除运算的全称量词场景)
通过对比不同连接运算的适用场景,结合分布式优化案例,可更深入理解半连接在实际数据库系统中的应用价值 —— 在保证查询结果正确的前提下,通过运算语义的精准匹配实现性能优化。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)