本节书摘来自华章出版社《数据库原理与应用(第3版)》一 书中的第3章,第3.5节,作者:何玉洁,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
关系模型源于数学。关系是由元组构成的集合,可以通过关系的运算来表达查询要求,而关系代数恰恰是关系操作语言的一种传统的表示方式,它是一种抽象的查询语言。
关系代数的运算对象是关系,运算结果也是关系。与一般的运算一样,运算对象、运算符和运算结果是关系代数的三大要素。
关系代数的运算可分为两大类:
传统的集合运算。这类运算完全把关系看成元组的集合。传统的集合运算包括集合的广义笛卡儿积运算、并运算、交运算和差运算。
专门的关系运算。这类运算除了把关系看成元组的集合外,还通过运算表达了查询的要求。专门的关系运算包括选择、投影、连接和除运算。
关系代数中的运算符可以分为四类:传统的集合运算符、专门的关系运算符、比较运算符和逻辑运算符。表3-9列出了这些运算符,其中比较运算符和逻辑运算符是配合专门的关系运算符来构造表达式的。

传统的集合运算是二目运算,设关系r和s均是n元关系,且相应的属性值取自同一个值域,则可以定义三种运算:并运算(∪)、交运算(∩)和差运算(-),但广义笛卡儿积并不要求参与运算的两个关系的对应属性取自相同的域。并、交、差运算的功能示意图如图3-5所示。
现在我们以图3-6a和图3-6b所示的两个关系为例,说明这三种传统的集合运算功能。
1.?并运算
关系r与关系s的并记为:
r∪s = {t | t∈r ∨ t∈s}
其结果仍是n目关系,由属于r或属于s的元组组成。
图3-7a显示了图3-6a和图3-6b两个关系的并运算结果。
2.?交运算
关系r与关系s的交记为:
r∩s = {t | t∈r ∧ t∈s }
其结果仍是n目关系,由属于r并且也属于s的元组组成。
图3-7b显示了图3-6a和图3-6b两个关系的交运算结果。
3.?差运算
关系r与关系s的差记为:
r - s = {t | t∈r ∧ t∈s }
图3-7c显示了图3-6a和图3-6b两个关系的交运算结果。
4.?广义笛卡儿积
广义笛卡儿积不要求参加运算的两个关系具有相同的目。
两个分别为m目和n目的关系r和关系s的广义笛卡儿积是一个(m+n)目的元组的集合。元组的前m个列是关系r的一个元组,后n个列是关系s的一个元组。若r有k1个元组,s有k2个元组,则关系r和关系s的广义笛卡儿积有k1×k2个元组,记作:
r×s = { tr ^ ts | tr∈r ∧ ts∈s }
tr ^ ts表示由两个元组tr和ts前后有序连接而成的一个元组。
任取元组tr和ts,当且仅当tr属于r且ts属于s时,tr和ts的有序连接即为r×s的一个元组。
实际操作时,可从r的第一个元组开始,依次与s的每一个元组组合,然后,对r的下一个元组进行同样的操作,直至r的最后一个元组也进行同样的操作为止,即可得到r×s的全部元组。
图3-8所示为广义笛卡儿积的操作示意。
专门的关系运算包括投影、选择、连接和除等操作,其中选择和投影为一元操作,连接和除为二元操作。
下面我们以表3-10~表3-12所示的三个关系为例,介绍专门的关系运算。各关系包含的属性含义如下。
student:sno(学号),sname(姓名),ssex(性别),sage(年龄),sdept(所在系)。
course:cno(课程号),cname(课程名),credit(学分),semester(开课学期)。
sc:sno(学号),cno(课程号),grade(成绩)。
1.?选择
选择(selection)运算是最简单的运算,它从指定的关系中选择某些元组形成一个新的关系,被选择的元组是满足指定的逻辑条件的。
选择运算表示为:
σf (r) ={ t | t∈r ∧ f(t)= ‘真’ }
其中,σ是选择运算符,r是关系名,t是元组,f是逻辑表达式,取逻辑“真”值或“假”值。
例3-4 查询计算机系的学生信息。
σsdept = ‘计算机系’(student)
结果如图3-9所示。
2.?投影
投影(projection)运算是对指定的关系进行垂直方向的选择,并形成一个新的关系。该操作包括如下两个过程:
1)选择指定的属性,形成一个可能含有重复行的关系。
2)删除重复行,形成新的关系。
投影运算表示为:
∏ a (r) = { t.a | t∈r }
其中,∏是投影运算符,r是关系名,a是被投影的属性或属性组。t.a表示t这个元组中对应属性(集)a的分量,也可以表示为t [a]。
例3-5 查询学生的姓名和所在系。
∏sname, sdept(student)
结果如图3-10所示。
3.?连接
连接运算用来连接相互之间有联系的两个关系,从而产生一个新的关系。这个过程由连接属性(字段)来实现。一般情况下这个连接属性是出现在不同关系中的语义相同的属性。
连接运算也称为θ运算。连接运算一般表示为:
其中a和b分别是关系r和s上语义相同的属性或属性组,θ是比较运算符。连接运算从r和s的广义笛卡儿积r×s中选择(r关系)在a属性组上的值与(s关系)在b属性组上值满足比较运算符θ的元组。
连接运算中最重要也是最常用的连接有两个,一个是等值连接,一个是自然连接。
当θ为“=”时的连接为等值连接,它是从关系r与关系s的广义笛卡儿积中选取a、b属性值相等的那些元组,即:
自然连接是一种特殊的连接,它要求两个关系中进行比较的分量必须是相同的属性组,并且在结果中要去掉重复的属性列。即,若关系r和s具有相同的属性组b,则自然连接可记作:
一般的连接运算是从行的角度进行运算,但自然连接还需要去掉重复的列,所以是同时从行和列的角度进行运算。
自然连接与等值连接的差别为:
自然连接要求相等的分量必须有共同的属性名,等值连接则不要求。
自然连接要求把重复的属性名去掉,等值连接却不这样做。
例3-6 对表3-10和表3-12所示的student和sc关系,分别进行如下的等值连接和自然连接运算。
等值连接:
自然连接:
等值连接的结果如图3-11所示,自然连接的结果如图3-12所示。
4.?除
1)除(division)运算的简单描述。
设关系s的属性是关系r的属性的一部分,则r÷s为这样一个关系:
此关系的属性是由属于r但不属于s的所有属性组成。
r÷s的任一元组都是r中某元组的一部分。但必须符合下列要求,即任取属于r÷s的一个元组t,则t与s的任一元组连接后,都为r中原有的一个元组。
除运算的示意图如图3-13所示。
2)除运算的一般形式。设有关系r(x,y)和s(y,z),其中x、y、z为关系的属性组,则:
r(x,y) ÷s(y,z) = r(x,y) ÷ ∏y (s)
3)关系的除运算是关系运算中最复杂的一种,关系r与s的除运算的以上叙述解决了r÷s关系的属性组成及其元组应满足的条件要求,但怎样确定r÷s的元组仍然没有说清楚。为了说清楚这个问题,首先引入象集的概念。
象集(image set):给定一个关系r(x,y),x和y为属性组。定义,当t[x] = x时,x在r中的象集为:
yx ={t[y] | t∈r∧t[x] = x}
上式中:t [y]和t [x]分别表示r中的元组t在属性组y和x上的分量的集合。
例如在表3-10所示的student关系中,有一个元组值为:
(0521101,张立,男,22,信息系)
假设x = {sdept,ssex},y = {sno,sname,sage},则上式中的t[x]的一个值
x = (信息系,男)
此时,yx为t[x] = x = (信息系,男)时所有t[y]的值,即:
yx = { (0521101,张立,22),(0521103,张海,20) }
也就是由信息系全体男生的学号、姓名、年龄所构成的集合。
又例如,对于表3-12所示的sc关系,如果设x = {sno},y = {cno,grade},则当x取“0512101”时,y的象集为:
yx = { (c01,90),(c02,86) }
当x取“0521102”时,y的象集为:
yx = {(c01,82),(c02,75),(c04,92),(c05,50)}
现在,我们再回过头来讨论除法的一般形式。
设有关系r (x,y)和s (y,z),其中x、y、z为关系的属性组,则:
r÷s = {tr [x] | tr∈r ∧ ∏y (s) yx}
图3-14给出了一个除运算的示例。
图3-14所示的除结果为至少选了“c01”和“c02”两门课程的学生的学号。
下面以表3-10~表3-12所示的student、course和sc关系为例,给出一些关系代数运算的综合例子。
例3-7 查询选了c02号课程的学生的学号和成绩。
∏sno, grade (σcno=‘c02’ (sc))
运算结果如图3-15所示。
例3-8 查询信息系选了c04号课程的学生的姓名和成绩。
由于学生姓名信息在student关系中,而成绩信息在sc关系中,因此这个查询同时涉及student和sc两个关系。因此首先应对这两个关系进行自然连接,得到同一位学生的有关信息,然后再对连接的结果执行选择和投影操作。具体如下:
∏sname, grade(σcno=‘c04’∧sdept=‘信息系’(sc student))
也可以写成:
∏sname, grade(σcno=‘c04‘(sc) σsdept=‘信息系‘(student))
后一种实现形式是首先在sc关系中查询出选了“c04”课程的集合,然后从student关系中查询出“信息系”学生的集合,最后再对这个集合进行自然连接运算(sno相等),这种查询的执行效率会比第一种形式高。
运算结果如图3-16所示。
例3-9 查询选了第2学期开设的课程的学生的姓名、所在系和所选的课程号。
这个查询的查询条件和查询列与两个关系有关:student(包含姓名和所在系信息)以及course(包含课程号和开课学期信息)。但由于student关系和course关系之间没有可以进行连接的属性(要求必须语义相同),因此,如果要让student关系和course关系进行连接,则必须要借助于sc关系,通过sc关系中的sno与student关系中的sno进行自然连接,并通过sc关系中的cno与course关系中的cno进行自然连接,可实现student关系和course关系之间的关联关系。
该示例的关系代数表达式如下:
∏sname, sdept, cno(σsemester=2(course sc student))
∏sname, sdept, cno(σsemester=2(course) sc student)
运算结果如图3-17所示。
例3-10 查询选了“vb”课程且考试成绩大于等于80的学生姓名、所在系和成绩。
这个查询涉及student、sc和course三个关系,在course关系中可以指定课程名,从student关系中可以得到姓名、所在系,从sc关系中可以得到成绩。
∏sname, sdept, grade(σcname=‘vb’ ∧ grade>=80(course sc student))
∏sname, sdept, grade(σcname=‘vb’(course) σgrade>=80(sc) student)
运算结果如图3-18所示。
例3-11 在全体学生中查询未选“计算机文化学”的学生姓名和所在系。
实现这个查询的关系代数表达式的基本思路是:从全体学生中去掉选了“计算机文化学”课程的学生,因此需要用到差运算。这个查询同样涉及student、sc和course三个关系。
∏sname, sdept(student)- ∏sname, sdept(σcname=‘计算机文化学’(course sc student))
∏sname, sdept(student)- ∏sname, sdept(σcname=‘计算机文化学’(course) sc student)
运算结果如图3-19所示。
图3-12 查询选了全部课程的学生的姓名和所在系。
编写实现这个查询的关系代数表达式的思考过程如下:
1)学生选课情况可用∏sno,cno(sc)表示。
2)全部课程可用∏cno(course)表示。
3)查询选了全部课程的学生的学号,可用除法运算得到,即:
∏sno,ono (sc) ÷∏cno (course)
4)从得到的sno集合再在student关系中找到对应的学生姓名(sname)和所在系(sdept),可用自然连接和投影操作组合实现。最终的关系代数表达式如下:
∏sname, sdept(student (∏sno,cno (sc) ÷∏cno (course)))
运算结果为空集合。
例3-13 查询信息系选了第2学期开设的全部课程的学生的学号和姓名。
编写实现这个查询的关系代数表达式的思考过程与例3-12类似,只是将2)改为“查询第2学期开设的全部课程”,这可用下列表达式表达:
∏cno (σsemester=2(course)
最终的关系代数表达式为:
∏sno, sname(σsdept=‘信息系’(student) (∏ sno,cno (sc) ÷ ∏cno(σsemester=2(course))))
运算结果如图3-20所示。
表3-13对关系代数操作进行了总结。
关系运算的优先级按从高到低的顺序为:投影、选择、笛卡儿乘积、连接和除(同级)、交、并和差(同级)。