1. 关系代数:数据库期末的“送分题”与“高分密码”
如果你正在为吉林大学《数据库系统概念》的期末考试发愁,看到“关系代数”这几个字,心里是不是稍微松了一口气?很多同学都听说过,这部分是“简单且分值高”的考点,是期末突击的黄金地带。但我想告诉你的是,它不仅仅是“只求及格的同学一定要掌握”的内容,更是你冲击高分、拉开差距的关键。我当年复习的时候,就靠着吃透关系代数,在卷面上稳稳拿下了大几十分,因为它逻辑清晰、套路固定,一旦掌握,解题就像做填空题一样顺畅。
关系代数到底是什么?你可以把它想象成一套专门用于“操作表格”的数学语言。我们数据库里存的是一张张表(关系),而关系代数提供了一系列运算符号,比如选择(σ)、投影(Π)、连接(⋈)等,让你能像搭积木一样,通过这些符号的组合,从原始表中筛选、拼接、计算出你想要的任何新表格。考试怎么考?绝不仅仅是让你默写定义。最常见的题型就是给出一两个业务场景(比如一个简单的员工薪资管理系统),然后让你用关系代数表达式写出查询语句,或者反过来,给你一个复杂的关系代数表达式,让你用中文描述它到底查了个啥。它的核心魅力在于“过程化”,每一步都清清楚楚,这正是我们应试时最喜欢的——有固定的步骤可循。
所以,这篇速成指南的目标,就是帮你把书上那些抽象的符号(σ、Π、⋈、∪、-、×、ρ),变成你手里锋利的解题工具。我们不会纠缠于过于形式化的数学定义,而是直接切入高频考点和实战解题套路。我会用同一个“薪资管理系统”案例贯穿始终,带你拆解典型例题,并时刻对比LaTeX表示法与SQL语句,让你知道“为什么这么写”以及“写出来对应什么”。相信我,跟着走一遍,你不仅能应付考试,还能真正理解数据库查询的核心思想。
2. 必须滚瓜烂熟的六大基本运算
这是关系代数的基石,也是考试出题概率最高的部分。你必须像背乘法口诀一样熟练。我们假设有三个表,这也是数据库课程里最经典的例子:
- EMP(员工表):包含
empno(员工号)、ename(姓名)、job(职位)、sal(薪资)、deptno(部门号)等属性。 - DEPT(部门表):包含
deptno(部门号)、dname(部门名称)、loc(地点)。 - SALGRADE(薪资等级表):包含
grade(等级)、losal(最低薪资)、hisal(最高薪资)。
2.1 选择(σ):横向筛选,找到符合条件的行
生活类比:就像你在Excel里使用“筛选”功能,只看“部门=技术部”且“薪资>8000”的那些行。
运算本质:从一张表里,横向筛选出满足特定条件的元组(行)。它不改变表的列结构,只是减少行数。
LaTeX表示:σ_{谓词条件}(关系名)
SQL对应:SELECT * FROM 表名 WHERE 条件;
实战拆解:
-
例题1:查询所有薪资大于等于3000的员工信息。
- 关系代数:
σ_{sal >= 3000}(EMP) - SQL:
SELECT * FROM EMP WHERE sal >= 3000; - 解读:谓词就是
sal >= 3000,作用于EMP表。结果是一张新的员工表,但里面只包含高薪员工的行。
- 关系代数:
-
例题2(复合条件):查询部门号为20,且薪资大于等于3000的员工信息。
- 关系代数:
σ_{deptno=20 ∧ sal>=3000}(EMP) - SQL:
SELECT * FROM EMP WHERE deptno=20 AND sal>=3000; - 踩坑提示:这里的逻辑连接词是“且”(∧,AND)。考试时务必注意区分“且”和“或”(∨,OR)。另一个易错点是属性名要写对,比如
deptno而不是dept_no,要完全参照题目给出的表结构。
- 关系代数:
2.2 投影(Π):纵向选择,挑出想要的列
生活类比:就像你制作一份只包含“姓名”和“电话”的通讯录,其他地址、职位等信息都不要。
运算本质:从一张表里,纵向选择出指定的属性(列)。它可能减少列数,并且会自动去除重复的行(这是关系模型的基本性质,非常重要!)。
LaTeX表示:Π_{属性1, 属性2, ...}(关系名)
SQL对应:SELECT 列1, 列2, ... FROM 表名;
实战拆解:
- 例题3:查看所有员工的姓名和职位。
- 关系代数:
Π_{ename, job}(EMP) - SQL:
SELECT ename, job FROM EMP; - 解读:结果是一张新表,只有两列:
ename和job。如果两个员工同名同职位,在结果中只会出现一行。
- 关系代数:
核心考点——运算组合:选择和投影是最常组合使用的运算。顺序很重要!
- 例题4:查询部门20里,薪资大于3000的员工的姓名和薪资。
- 思路:先横向筛选(选择),再纵向挑列(投影)。
- 关系代数:
Π_{ename, sal}(σ_{deptno=20 ∧ sal>3000}(EMP)) - SQL:
SELECT ename, sal FROM EMP WHERE deptno=20 AND sal>3000; - 为什么先选择再投影? 从效率上理解,先过滤掉大部分不满足条件的行,再对剩下的少量行进行投影,计算量更小。虽然关系代数只定义结果,不规定执行顺序,但按这个顺序写表达式更符合逻辑。
2.3 并(∪)、差(-)、笛卡尔积(×):集合的玩法
这三者都是对两个关系(表)进行运算,要求参与运算的两个关系必须具有相容性。
并运算(∪):
- 生活类比:合并两份名单,去掉重复的人。
- 本质:返回出现在第一个表或第二个表或两个表中的所有不重复的元组。
- 要求:两个表必须同构,即属性数目相同,且对应属性的域(数据类型)相同。
- 例题5:查询所有“经理”或“薪资大于5000”的员工编号和姓名。(假设这是两个独立的查询结果集R和S)
- 关系代数:
R ∪ S - SQL:
SELECT empno, ename FROM EMP WHERE job='MANAGER' UNION SELECT empno, ename FROM EMP WHERE sal>5000; - 注意:SQL中用
UNION会自动去重。如果不想去重,用UNION ALL,但关系代数中的∪定义就是去重的。
- 关系代数:
差运算(-):
- 生活类比:从一份全员名单中,减去已经离职的人员名单,得到在职名单。
- 本质:返回所有在第一个表中但不在第二个表中的元组。
- 例题6:查询在部门10但不在部门20的员工信息。(这通常需要先分别投影出部门10和部门20的员工ID,再做差集)
- 关系代数:
Π_{empno}(σ_{deptno=10}(EMP)) - Π_{empno}(σ_{deptno=20}(EMP)) - SQL:
SELECT empno FROM EMP WHERE deptno=10 MINUS SELECT empno FROM EMP WHERE deptno=20;(注意,有些数据库用EXCEPT)
- 关系代数:
笛卡尔积(×):
- 生活类比:把两个列表里的所有元素进行两两配对。比如列表A=[1,2],列表B=[‘a’,‘b’],结果就是{(1,‘a’), (1,‘b’), (2,‘a’), (2,‘b’)}。
- 本质:将两个表的每一行都与另一个表的每一行进行组合。如果表R有m行,表S有n行,结果就有 m*n 行。属性数是两者之和。
- 危险操作:现实中极少直接使用,因为会产生巨量无意义的中间结果。但它是一切连接运算(如自然连接)的理论基础。
- 例题7:
EMP表有5个属性、8行;DEPT表有3个属性、3行。EMP × DEPT的结果将有 5+3=8 个属性,8*3=24 行。结果中会出现一个员工和所有部门的组合,这显然大部分是无效信息。
2.4 更名(ρ):给表和列起个别名
为什么需要它? 当进行自连接(一个表和自己连接),或者运算结果需要被后续步骤引用时,我们必须给中间结果或属性起一个唯一的名字。
LaTeX表示:ρ_{新关系名}(原表达式) 或 ρ_{新关系名(新属性名列表)}(原表达式)
SQL对应:AS 关键字,例如 FROM EMP AS E1,或者 SELECT ename AS 姓名。
实战拆解:
- 例题8(属性更名):查询员工姓名和薪资,并将结果列名显示为“姓名”和“工资”。
- 关系代数:
ρ_{结果(姓名, 工资)}(Π_{ename, sal}(EMP)) - SQL:
SELECT ename AS 姓名, sal AS 工资 FROM EMP;
- 关系代数:
- 例题9(关系更名,为后续连接铺垫):这个我们留到下一节“自然连接”里详细讲,它是更名运算最典型的应用场景。
3. 搞定连接与集合交:解决多表查询难题
学完了基本运算,我们已经能处理单表查询了。但数据库的精髓在于关联多张表。连接运算就是用来干这个的,而集合交则提供了一种特殊的筛选思路。
3.1 自然连接(⋈):智能匹配关联
这是考试绝对的重中之重,必须彻底掌握。
生活类比:你有员工表(有部门号)和部门表(有部门号和部门名)。自然连接就能自动根据相同的“部门号”,把员工和他所在的部门信息拼接到一行里。
本质:自动找出两个表中所有同名同类型的属性,在这些属性上取值相等的元组进行匹配拼接,结果中同名属性只保留一列。
LaTeX表示:R ⋈ S
实战拆解:
- 例题10:查询每位员工及其所在部门的详细信息。
- 已知:
EMP表有deptno,DEPT表也有deptno。 - 关系代数:
EMP ⋈ DEPT - SQL:
SELECT * FROM EMP NATURAL JOIN DEPT;或者更常见的:SELECT * FROM EMP, DEPT WHERE EMP.deptno = DEPT.deptno;(这是等值连接,结果列会包含两个deptno,需注意区别)。 - 结果:新表包含
empno, ename, job, sal, deptno, dname, loc。看,deptno只出现了一次。
- 已知:
用基本运算实现自然连接(重要考点!): 很多考题会要求你用选择、投影、笛卡尔积和更名来表达自然连接,这是检验你是否理解其本质的好方法。
- 计算笛卡尔积:
R × S - 选择同名属性值相等的行:假设R和S共有的属性是
A1, A2, ...,则进行选择:σ_{R.A1=S.A1 ∧ R.A2=S.A2 ∧ ...}(R × S) - 投影去掉重复的列:
Π_{去重后的属性集}(上述结果)公式:R ⋈ S = Π_{R∪S的属性集合}(σ_{R.共同属性=S.共同属性}(R × S))
3.2 集合交(∩):另一种视角的筛选
本质:返回同时属于两个关系的元组。
用差运算表示:这是一个重要考点!R ∩ S = R - (R - S)。想想集合的文氏图,很容易理解。
何时用:当查询条件可以理解为“既要...又要...”,且这两个条件分别来自两个独立的子查询结果时。
例题11:查询既在“研发部”工作,又是“经理”的员工。(假设已通过连接查询得到“研发部员工”集合R和“经理”集合S)
- 关系代数:
R ∩ S - SQL:
SELECT ... INTERSECT SELECT ...;(或用WHERE EXISTS子查询实现)
3.3 外连接(⟕, ⟖, ⟗):处理“缺失”的信息
自然连接只返回能匹配上的行。但如果一个员工(左表)还没有分配部门(右表无匹配),或者一个部门(右表)还没有员工(左表无匹配),自然连接中这些信息就会丢失。外连接就是为了保留这些“孤儿”元组。
- 左外连接(⟕):以左表为基准,保留左表所有元组。右表匹配不上的属性填
NULL。- 例题:列出所有员工及其部门,即使该员工未分配部门也要列出。
- SQL:
SELECT * FROM EMP LEFT OUTER JOIN DEPT ON EMP.deptno = DEPT.deptno;
- 右外连接(⟖):以右表为基准,保留右表所有元组。
- 全外连接(⟗):左右两边的“孤儿”都保留。
考试中,外连接的题目通常会描述“所有...即使没有...”这样的场景,看到这种描述就要立刻反应过来。
4. 冲刺高分:掌握扩展运算与复杂表达式构造
如果你只想及格,掌握前三部分已经足够。但如果你想拿高分,拉开分数差距,那么扩展运算和复杂表达式的构造能力就是你的“杀手锏”。
4.1 广义投影(Π):在投影时进行计算
普通投影只是选列,广义投影允许你在选列的同时,对列进行算术或字符串运算。
LaTeX表示:Π_{表达式1 AS 新名1, 表达式2 AS 新名2, ...}(关系)
例题12:查询员工姓名及其年薪(假设月薪为sal,年薪为sal*12)。
- 关系代数:
Π_{ename, sal*12 AS annual_sal}(EMP) - SQL:
SELECT ename, sal*12 AS annual_sal FROM EMP;这大大增强了查询的表现力,可以应对“查询增长率”、“查询折扣后价格”等灵活场景。
4.2 聚集运算(G):分组统计的利器
这是数据分析的核心,也是考试大题的热门考点。聚集函数包括:count(计数)、sum(求和)、avg(平均)、max(最大)、min(最小)。
LaTeX表示:_{分组属性}G_{聚集函数(属性) AS 别名}(关系)
SQL对应:SELECT 分组属性, 聚集函数(属性) FROM 表 GROUP BY 分组属性;
实战拆解:
- 例题13:统计每个部门的员工人数和平均薪资。
- 关系代数:
_{deptno}G_{count(empno) AS emp_count, avg(sal) AS avg_sal}(EMP) - SQL:
SELECT deptno, COUNT(empno) AS emp_count, AVG(sal) AS avg_sal FROM EMP GROUP BY deptno;
- 关系代数:
- 例题14(带Having条件):查询平均薪资大于3000的部门编号和平均薪资。
- 思路:先分组聚集得到临时结果,再对这个临时结果进行选择(筛选)。
- 关系代数:
σ_{avg_sal > 3000}(_{deptno}G_{avg(sal) AS avg_sal}(EMP)) - SQL:
SELECT deptno, AVG(sal) AS avg_sal FROM EMP GROUP BY deptno HAVING AVG(sal) > 3000; - 关键区别:
WHERE是对原始行筛选,在聚集之前;HAVING是对分组结果筛选,在聚集之后。在关系代数中,这体现为选择运算σ应用在不同的子表达式上。
4.3 复杂表达式构造与赋值(←)
面对复杂的多步骤查询,直接写一个很长的嵌套表达式容易出错且难以阅读。这时可以用赋值运算来分步拆解。
LaTeX表示:临时关系名 ← 表达式
作用:纯粹是为了让表达式更清晰,便于理解和书写,不影响最终结果。
例题15:查询“比所在部门的平均薪资还要高”的员工信息。
这是一个经典难题。我们可以分三步用赋值来思考:
DeptAvg ← _{deptno}G_{avg(sal) AS dept_avg_sal}(EMP)-- 先算出每个部门的平均薪资,得到一个临时表(部门号,平均薪资)。EmpWithAvg ← EMP ⋈ DeptAvg-- 将员工表与这个临时表按部门号自然连接,这样每个员工后面都带上了他所在部门的平均薪资。Result ← σ_{sal > dept_avg_sal}(EmpWithAvg)-- 最后筛选出薪资大于部门平均薪资的员工。 最终答案可以把这三步赋值语句写出来,也可以把右边代入左边,合并成一个表达式(可能会很长)。在考试时,如果题目没有明确要求,写出分步的赋值过程通常更能体现你的思路,也更不容易出错。
5. 期末实战:从审题到书写的全流程指南
最后,我们来模拟一下考场上的实战流程。拿到一道关系代数大题,不要慌,按这个步骤来:
第一步:仔细审题,明确输入输出
- 找出题目中涉及的所有关系(表),在草稿纸上简单列出它们的属性。这是你的“作战地图”,绝对不能错。
- 用笔划出查询的最终目标:要输出哪些属性(列)?这就是你表达式最外层的投影列表。
- 理解查询的约束条件:哪些是过滤行的条件(对应选择)?哪些是需要关联表才能获得的条件(对应连接)?哪些是统计条件(对应聚集和分组)?
第二步:从内到外,分步构建
- 先做连接:如果需要关联多个表,先从自然连接或等值连接开始,把相关的信息拼接到一起。如果需要处理空值,考虑外连接。
- 再做选择:在连接好的大表上,应用所有的行过滤条件。注意条件的逻辑连接(AND/OR)。
- 处理分组与聚集:如果需要统计,在这一步引入分组和聚集运算。记住,
HAVING条件是对聚集结果的选择。 - 最后投影:在表达式的最外层,用投影运算精确选出题目要求输出的那些列。如果需要计算新列,用广义投影。
第三步:检查与优化
- 检查属性名:确保所有引用的属性名在当前的子表达式中是存在的。特别是在使用更名后,要使用新名字。
- 检查相容性:检查所有并、差、交运算两边的子表达式是否属性相容。
- 思考等价写法:有时候,选择和投影的顺序可以交换(
Π(σ(...))在某些条件下等价于σ(Π(...))),选择条件可以下推到连接之前以优化。虽然考试不强制要求优化,但写出更高效的表达式能展示你的深度。 - 对照SQL:在脑子里默默把你的关系代数表达式翻译成SQL。这是一个极好的验证方法,因为SQL更直观,能帮你发现逻辑错误。
我当年的一个血泪教训:有一次模拟考,题目是“查询没有员工的部门名称”。我一开始写成了 Π_{dname}(DEPT - Π_{deptno}(EMP)),这显然是错的,因为差运算要求两边属性完全一致。正确思路应该是:先找出有员工的部门号(Π_{deptno}(EMP)),然后从部门表中找出部门号不在这个集合里的部门(这里要用到差运算,但需要对部门表先投影出部门号),最后再投影出部门名。最终表达式是:Π_{dname}(σ_{deptno NOT IN ...}(DEPT)) 或者用差运算表示为 Π_{dname}(DEPT) - Π_{dname}(DEPT ⋈ EMP)?不,后者不对。最稳妥的还是用差运算的基本形式:Π_{dname}( Π_{deptno, dname}(DEPT) - Π_{deptno, dname}(DEPT ⋈ EMP) )。看,一个小小的“没有”查询,就能综合考察投影、连接、差运算和对空值的理解。多练几道这种题,手感就出来了。
关系代数就像数据库世界的乐高积木,符号是有限的,但组合起来能构建出无限复杂的查询。期末突击的关键不在于死记硬背每一个定义,而在于通过反复练习典型例题,形成“条件反射”——看到“查询...和...的信息”想到连接,看到“每个...的...”想到分组聚集,看到“没有...”想到差运算或外连接。把这份指南里的例题和思路消化掉,再找几套往年的真题练练手,你一定能发现,关系代数这块,真的就是那张最可靠的“高分通行证”。
4万+



被折叠的 条评论
为什么被折叠?



