连接查询
前面的查询都是针对一个表进行的。若一个查询同时涉及两个以上的表,则称之为连接查询。连接查询是关系数据库中最主要的查询,包括等值连接查询、自然连接查询、非等值连接查询、自身连接查询、外连接查询和复合条件连接查询等。
①等值与非等值连接查询
连接查询的WHERE子句中用来连接两个表的条件称为连接条件或连接谓词,其一般格式为
[<表名1>.]<列名1><比较运算符>[<表名2>.]<列名2>
其中比较运算符主要有=、>、<、>=、<=、!=(或<>)等。
此外连接谓词还可以使用下面形式:
[<表名1>.]<列名1>BETWEEN [<表名2>.]<列名2>AND [<表名2>.]<列名3>
当连接运算符为=时,称为等值连接。使用其他运算符称为非等值连接。
连接谓词中的列名称为连接字段。连接条件中的各连接字段类型必须是可比的,但名字不必相同。
【例1】查询每个学生及其选修课程的情况。
学生情况存放在Student表中,学生选课情况存放在SC表中,所以本查询实际上涉及Student与SC两个表。这两个表之间的联系是通过公共属性Sno实现的。
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno;
假设Student表、SC表的数据如学生-课程数据库所示,该查询的执行结果如下图所示。

本例中,SELECT子句与WHERE子句中的属性名前都加上了表名前缀,这是为了避免混淆。如果属性名在参加连接的各表中是唯一的,则可以省略表名前缀。
关系数据库管理系统执行该连接操作的一种可能过程是:首先在表Student中找到第一个元组,然后从头开始扫描SC表,逐一查找与Student第一个元组的Sno相等的SC元组,找到后就将Student中的第一个元组与该元组拼接起来,形成结果表中一个元组。SC全部查找完后,再找Student中第二个元组,然后再从头开始扫描SC,逐一查找满足连接条件的元组,找到后就将Student中的第二个元组与该元组拼接起来,形成结果表中一个元组。重复上述操作,直到Student中的全部元组都处理完毕为止。这就是嵌套循环连接算法的基本思想。如下图所示。

如果在SC表Sno上建立了索引的话,就不用每次全表扫描SC表了,而是根据Sno值通过索引找到相应的SC元组。用索引查询SC中满足条件的元组一般会比全表扫描快。
若在等值连接中把目标列中重复的属性列去掉则为自然连接。
【例2】对例1用自然连接完成。
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student,SC
WHERE Student.Sno=SC.Sno;
本例中,由于Sname,Ssex,Sage,Sdept,Cno和Grade属性列在Student表与SC表中是唯一的,因此引用时可以去掉表名前缀;而Sno在两个表都出现了,因此引用时必须加上表名前缀。
一条SQL语句可以同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的复合条件。
【例3】查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND SC.Cno='2' AND SC.Grade>90;
该查询的一种优化(高效)的执行过程是,先从SC中挑选出Cno=2'并且Grade>90的元组形成一个中间关系,再和Student中满足连接条件的元组进行连接得到最终的结果关系。
②自身连接
连接操作不仅可以在两个表之间进行,也可以是一个表与其自己进行连接,称为表的自身连接。
【例4】查询每一门课的间接先修课(即先修课的先修课)。
在Course表中只有每门课的直接先修课信息,而没有先修课的先修课。要得到这个信息,必须先对一门课找到其先修课,再按此先修课的课程号查找它的先修课程。这就要将Course表与其自身连接。
为此,要为Course表取两个别名,一个是FIRST,另一个是SECOND。

完成该查询的SQL语句为

③外连接
在通常的连接操作中,只有满足连接条件的元组才能作为结果输出。如例1的结果表中没有201215123和201215125两个学生的信息,原因在于他们没有选课,在SC表中没有相应的元组,导致Student中这些元组在连接时被舍弃了。
有时想以Student表为主体列出每个学生的基本情况及其选课情况。若某个学生没有选课,仍把Student的悬浮元组保存在结果关系中,而在SC表的属性上填空值NULL,这时就需要使用外连接。外连接的概念已经在第二章中讲解过。可以参照例5改写例1。
【例5】

左外连接列出左边关系(如本例Student)中所有的元组,右外连接列出右边关系中所有的元组。
④多表连接
连接操作除了可以是两表连接、一个表与其自身连接外,还可以是两个以上的表进行连接,后者通常称为多表连接。
【例6】查询每个学生的学号、姓名、选修的课程名及成绩。
本查询涉及三个表,完成该查询的SQL语句如下:
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course
WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;
关系数据库管理系统在执行多表连接时,通常是先进行两个表的连接操作,再将其连接结果与第三个表进行连接。本例的一种可能的执行方式是,先将Student表与SC表进行连接,得到每个学生的学号、姓名、所选课程号和相应的成绩,然后再将其与Course表进行连接,得到最终结果。







