关系代数
关系代数(relational algebra):一种过程化查询语言。包括一个运算的集合,集合中运算以一个或两个关系为输入,产生一个新的关系作为结果。
关系代数的基本运算包括:选择、投影、并、集合差、笛卡尔积、更名。
其他运算:集合交、自然连接、赋值,可用基本运算来定义。
关系运算的结果自身也是一个关系,可用一个关系运算表达式作为另一个关系运算的参数,因此可以把多个关系代数运算组合成一个关系代数表达式(relational-algebra expression)。
关系代数定义了一套在表上运算且输出结果也是表的代数运算。这些运算可以混合使用来得到表达所希望查询的表达式。关系代数定义了关系查询语言中使用的基本运算。
关系代数运算可分为:基本运算、附加的运算(可用基本运算表达)、扩展的运算(其中一些扩展了关系代数的表达能力)。
关系代数是一种简介的、形式化的语言,不适用于那些偶尔使用数据库系统的用户,因此商用数据库系统采用有更多“语法修饰”的语言。(SQL基于关系代数)
1. 基本运算
一元运算:对一个关系进行运算,包括选择、投影、更名运算。
二元运算:对两个关系进行运算,包括并、集合差、笛卡尔积运算。
选择(select)运算:选出满足给定谓词的元组,用小写sigma(σ)表示,下标为谓词,括号中为参数关系。
e.g. 找出关系instructor中属于物理系的所有教师
σdept_name=”Physics”(instructor)
e.g. 找出工资额大于90000美元的所有教师
σsalary>90000(instructor)
可用连词and(∧)、or(∨)、not(¬)将多个谓词合并为一个较大的谓词。
e.g. 找出属于物理系且工资大于90000美元的所有教师
σdept_name=”Physic”∧salary>90000(instructor)
选择谓词中可包括两个属性的比较。
e.g. 找出所有系名与楼名相同的系
σdept_name=building(department)
注意:关系代数中的属于select与SQL中的关键词select含义不同,关系代数中属于select对应SQL中的where。
投影(project)运算:返回作为参数的关系,但把某些属性排除在外,所有重复行均被去除。用大写pi(Π)表示,下标为在结果中出现的属性,括号中为参数关系。
e.g. 列出所有教师的ID、name和salary,而不关系dept_name。
ΠID, name, salary(instructor)
e.g. 找出物理系所有教师的名字
Πname(σdept_name=”Physics”(instructor))
并(union)运算: 可将两个集合并起来,找出出现在两个集合之一或同时出现在两个集合中的所有元组。用∪表示。
e.g. 找出开设在2009年秋季学期或者2010年春季学期或者这二者皆开的所有课程的集合。
Πcourse_id(σsemester=”Fall”∧year=2009(section))∪Πcourse_id(σsemester=”Spring”∧year=2010(section))
/*注意:结果中重复值只留下单个元组。*/
必须保证做并运算的关系是相容的,否则运算结果没有意义。要使并运算r∪s有意义(r和s可以是数据库关系或作为关系代数表达式结果的临时关系),要求以下两个条件同时成立:
a. 关系r和s必须是同元的(属性数目相同)。
b. 对所有的i,r的第i个属性的域必须和s的第i个属性的域相同。
集合差(set-difference)运算:表达式r-s包含所有在r中而不在s中的元组的关系。
e.g. 找出所有开设在2009年秋季学期但是在2010年春季学期不开的课程。
Πcourse_id(σsemester=”Fall”∧year=2009(section))-Πcourse_id(σsemester=”Spring”∧year=2010(section))
类似并运算,必须保证做集合叉运算的关系是相容的,否则运算结果没有意义。要使集合差运算r-s有意义,要求一下两个条件同时成立:
a. 关系r和s必须是同元的。
b. 对所有的i,r的第i个属性的域必须和s的第i个属性的域相同。
笛卡尔积(Cartesian-product)运算:将任意两个关系的信息组合在一起,结果中包含所有可能的元组对。关系r1和r2的笛卡尔积写作r1×r2,假如r1有n1个元组,r2有n2个元组,则可由n1×n2种方式选择元组对。
由于相同的属性名可能同时出现在r1和r2中,需要一个命名机制来区别这些属性。可采用把属性所来自的关系名称附加到该属性上的方法。
e.g. r = instructor×teaches的关系模式
(instructor.ID, instructor.name, instructor.dept_name, instructor.salary, teaches.ID, teaches.course_id, teaches.sec_id, teaches.semeser, teaches.year)
/*对于只在两个关系模式之一出现的属性,通常省略其关系名前缀。因此可将r的关系模式写作:*/
(instructor.ID, name, dept_name, salary, teaches.ID, course_id, sec_id, semester, year)
注意:该命名规则规定作为笛卡尔积运算参数的关系名称必须不同,因此当某个关系要与自身做笛卡尔积或在笛卡尔积中使用关系代数表达式结果时可能产生问题,可通过更名运算给关系一个名字以引用其属性来解决。
e.g. 找出物理系中的所有教师,以及他们所教授的所有课程。
/* σdept_name=”Physics”(instructor×teaches)只包含物理系的教师的元组,但course_id列可能包含并非这些教师所教授的课程;
σinstructor.ID=teaches.ID(σdept_name=”Physics”(instructor×teaches))包含物理系教师以及他们所教的课程的元组;
Πname, course_id(σinstructor.ID=teaches.ID(σdept_name=”Physics”(instructor×teaches)))投影得到需要的教师名字列和corse_id列。*/
Πname, course_id(σinstructor.ID=teaches.ID(σdept_name=”Physics”(instructor×teaches)))
/*用关系代数表达查询的方法并不唯一,也可采用如下等价查询:*/
Πname, course_id(σinstructor.ID=teaches.ID((σdept_name=”Physics”(instructor))×teaches))
更名(rename)运算:给关系代数表达式的结果赋上名字以供引用,用小写rho(ρ)表示。
表达式ρx(E)返回给定关系代数表达式E的结果并把名字x赋给它。更名运算也可用于关系,可得到具有新名字的一个相同的关系。
更名运算的另一形式:ρx(A1, A2, …, An)(E)。假设关系代数表达式E是n元的,运算返回表达式E的结果,并把名字x赋给它,同时将各属性更名为A1, A2, …, An。
e.g. 找出大学里的最高工资
/*步骤1:计算出一个由非最高工资组成的临时关系。
首先通过更名运算引用其中一个instructor关系以便计算笛卡尔积instructor×instructor,再构造选择运算比较任意两个出现在同一元组中的salary选择较低的元组。通过投影选取instructor.salary列得到非最高工资构成的临时关系*/
Πinstructor.salary (σinstructor.salary<d.salary(instructor×ρd(instructor)))
/*步骤2:计算关系Πsalary (instructor)和刚才计算出的非最高工资构成的临时关系的集合差,得到结果。*/
Πsalary (instructor)-Πinstructor.salary (σinstructor.salary<d.salary(instructor×ρd(instructor)))
更名运算不是必须的,因为可以用位置标记隐含地作为关系(或关系代数表达式运算的结果)的属性名,用$1、$2、…指代第一个属性、第二个属性…以此类推。
e.g. 用位置标记来计算大学里的非最高工资构成的临时关系
/*在笛卡尔积(instructor×instructor)中,$4代表第一个instructor的属性salary,$8代表第二个instructor的属性salary。*/
Π$4(σ$4<$8(instructor×instructor))
如果一个二元运算需要区分其运算对象的两个关系,也可使用为指标及作为关系的名称。E.g. $R1指代第一个作为运算对象的关系,$R2指代第二个关系。
2. 关系代数的形式化定义
关系代数中基本的表达式是以下二者之一:a. 数据库中的一个关系;b. 一个常数关系。
常数关系:可在{}内列出其元组来表示。
E.g. {(22222, Einstein, Physics, 95000), (76543, Singh, Finance, 80000)}
设E1和E2都是关系代数表达式,则以下这些都是关系代数表达式:
·E1∪E2
·E1-E2
·E1×E2
·σp(E1),P为E1属性上的谓词。
·ΠS(E1),S为E1上某些属性的列表。
·ρx(E1),x为E1结果的新名字。
3. 附加的关系代数表达式
关系代数的基本运算足以表达任何关系代数查询。附加的关系代数运算不能增强关系代数的表达能力,但可以简化一些常用的查询。
集合交(intersection)运算 (∩)
e.g. 找出在2009年秋季和2010年春季都开设的课程
Πcourse_id(σsemester=”Fall”∧year=2009(section))∩Πcourse_id(σsemester=”Spring”∧year=2010(section))
任何使用了集合交的关系代数表达式都可以通过一对集合差运算替代重写:
r∩s=r-(r-s)
自然连接(natural join)运算 (⋈):首先形成两个参数关系的笛卡尔积,然后基于两个关系模式中都出现的属性上的相等性进行选择(只考虑两个关系在所有相同属性有相同值的元组组成的元组对),最后去除重复属性(并不重复记录在两个关系模式中都出现的属性)。
自然连接的形式化定义:
设r(R)和s(S)(模式分别为R和S的两个关系),其自然连接的结果r ⋈ s是模式R∪S上的一个关系。
r ⋈ s = ΠR∪S(σr.A1=s.A1∧r.A2=s.A2∧…∧r.An=s.An(r×s)),其中R∩S={A1, A2, …, An}。
如果r和s不含有任何相同属性,即R∩S=∅,则r ⋈ s = r×s。
所列出的属性的顺序:两个关系模式的相同属性排在最前,只属于第一个关系模式的属性其次,只属于第二个关系模式的属性最后。
e.g. 找出所有教师的姓名,连同他们教的所有课程的course_id。
/*instructor和teaches自然连接的结果模式为(ID, name, dept_name, salary, course_id),投影后得到模式为(name, course_id)的关系。*/
Πname, course_id(instructor ⋈ teaches)
考虑两个关系模式R和S,可将关系模式看作集合:用R∩S表示同时出现在R和S中的属性名,用R∪S表示出现在R中、S中或在二者中都出现的属性名,用R-S表示出现在R中而不出现在S中的属性名,用S-R表示出现在S中而不出现在R中的属性名。
自然连接时可结合的(associative)。
e.g. 找出计算机系的所有教师,以及他们教授的所有课程的名称。
/* 自然连接instructor ⋈ teaches ⋈ course的执行顺序可能为
(instructor ⋈ teaches) ⋈ course 或 instructor ⋈ (teaches ⋈ course),二者是等价的。*/
Πname, title(σdept_name=”Comp.Sci.”(instructor ⋈ teaches ⋈ course))
theta连接(theta join)运算:是自然连接的扩展。
考虑关系r(R)和s(S),θ是模式R∪S的属性上的谓词。r ⋈θ s = σθ(r×s)
赋值(assignment)运算 (←):可用于给临时关系变量赋值,便于写关系代数表达式。
e.g. 自然连接运算r ⋈s的定义可写作
temp1←r×s
temp2←σr.A1=s.A1∧r.A2=s.A2∧…∧r.An=s.An(temp1)
result = ΠR∪S(temp2)
对关系代数查询而言,赋值必须是赋给一个临时关系变量。对永久关系的赋值形成了对数据库的修改。
外连接(outer-join)运算:连接运算的扩展,可处理缺失的信息(因为不满足自然连接条件而不能在自然连接结果中找到的元组),避免信息的丢失。
外连接运算与自然连接运算类似,不同之处在于外连接在连接计算结果中添加额外的带空值的元组,以此保留在连接中丢失的元组。
外连接运算有三种形式:
左外连接(left outer join)(⟕):取出左侧关系中所有与右侧关系的任一元组都不匹配的元组,用空值填充所有来自右侧关系的属性,再把产生的元组加到自然连接的结果中。所有来自左侧关系的信息在左外连接结果中都得到保留。
右外连接(right outer join)(⟖):与左外连接相对称,用空值填充来自右侧关系的所有与左侧关系任一元组都不匹配的元组,将结果加到自然连接的结果中。所有来自右侧关系的信息在右外连接中都得到保留。
全外链接(full outer join)(⟗):既做左外连接又做右外连接,既填充左侧关系中与右侧关系的任一元组都不匹配的元组,又填充右侧关系中与左侧关系任一元组都不匹配的元组,并把结果都加到连接的结果中。
注意:外连接运算可用基本关系代数运算表示。E.g. 左外连接运算r⟕s可写作
/*其中常数关系{(null, …, null)}的模式为S-R。*/
(r ⋈ s)∪(r - ΠR(r ⋈ s)) × {(null, …, null)}
4. 扩展的关系代数运算
扩展的关系代数(extended relational-algebra)运算可实现一些不能用基本的关系代数运算来表达的查询。
广义投影(generalized-projection):通过允许在投影列表使用算术运算和字符串函数等来对投影进行扩展。
运算形式:
ΠF1, F2, …, Fn(E)
其中E为任意关系代数表达式,F1, F2, …, Fn都是涉及常量以及E的模式中属性的算术表达式。
最基本情况下算术表达式可以仅仅是一个属性或常量,在表达式中可使用对数值属性或产生数值结果的表达式的+、-、*、/等代数运算。广义投影还允许其他数据类型上的运算(如字符串的串接)。
e.g. 查询每个教师的ID、name、dept_name以及每月的工资
ΠID, name, dept_name, salary/12(instructor)
聚集运算(