9.3 表的连接类型
9.3.1 自连接
自连接是指表与其自身进行连接,这就需要用到前面介绍的表别名。下面通过一个具体实例来讲解自连接的应用。
实例5 自连接的使用方法
查询成绩中存在不及格课程的学生的姓名、所在系、所有的课程及成绩信息。如果采用前面介绍的SELECT语句查询方法,该实例的实现要分为两步。
1.查询存在不及格课程的学生的学号
之所以查询学号,是因为学号是学生的惟一标识信息。代码:
SELECT DISTINCT SNO |
运行结果如图9.5所示。
图9.5 不及格课程学生的学号 |
注意 因为可能有的学生的不及格课程多于1门,因此在SELECT子句中使用了DISTINCT关键词,去除重复的学号。
2.根据学号查询相关信息
根据查询的学号结果,查询这些学号的学生的姓名、所在系、所有所修课程及成绩信息。代码:
SELECT SNAME, DNAME, CNO, MARK |
运行结果如图9.6所示。
图9.6 根据学号查询的相关信息 |
而如果采用表的自连接,只要通过一步查询就可以实现该实例。代码:
SELECT DISTINCT S1.SNAME, S1.DNAME, S1.CNO, S1.MARK |
运行结果如图9.7所示。
代码中,FROM子句中的两个表实际上都是表STUDENT。为了独立地使用它们,采用上节介绍的表别名方法,分别为其取别名S1和S2。这样就可以在WHERE子句中,使用S2设定分数查询条件,而在SELECT子句中,使用S1查询满足条件的结果。
需要说明一点,SELECT子句同样要有关键字DISTINCT,如果没有使用DISTINCT关键字,如下面的代码:
图9.7 采用表的自连接执行的查询结果 |
SELECT S1.SNAME, S1.DNAME, S1.CNO, S1.MARK |
运行结果如图9.8所示。
图9.8 采用表的自连接但没有去除重复记录的查询结果 |
可以发现,结果表中出现了重复的记录。下面分析一下代码的执行过程,从中就不难发现重复记录产生的原因。
系统首先执行FROM子句,将STUDENT表S1与它自身S2的笛卡尔积,作为中间表。实际上,该中间表的每一条记录包含两部分信息,一部分是S1的记录,一部分是S2的记录。而后执行WHERE子句,在中间表中,搜索S2中成绩低于60分的学生的记录,同时要求记录中S1与S2是同一个学生的记录即学号相同。最后执行SELECT语句,从中间表获取S1中相应的信息作为结果表。
当执行WHERE子句,从中间表中逐条搜索S2中成绩低于60分的学生的记录时,由于孙庆有两门课程不及格,所以对于每门不及格的记录都满足搜索条件,因此导致了从S1得到的信息中出现了重复记录。
简单来说,中间表是没有重复记录的,但是S1部分字段是有重复的,而结果集提取的只是S1部分的字段,因此就有可能有重复记录。