数据库多表连接查询的实现方式
连接查询是关系数据库中最主要的查询,主要包括自连接、内连接、外连接和交叉连接。通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。 在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,然后通过连接进行查询。
内连接的连接查询结果集中仅包含满足条件的行,内连接是SQL Server缺省的连接方式,可以把INNERJOIN简写成JOIN,根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种;交叉连接的连接查询结果集中包含两个表中所有行的组合;外连接的连接查询结果集中既包含那些满足条件的行,还包含其中某个表的全部行,有3种形式的外连接:左外连接、右外连接、全外连接。
一、交叉连接
交叉连接即笛卡儿乘积,是指两个关系中所有元组的任意组合。一般情况下,交叉查询是没有实际意义的。
例如:如果希望得到学生表和选课表两个关系模式的乘积,查询语句为
SELECT *
FROM学生表CROSS JOIN选课表
二、内连接
内连接是一种最常用的连接类型。内连接查询实际上是一种任意条件的查询。使用内连接时,如果两个表的相关字段满足连接条件,就从这两个表中提取数据并组合成新的记录,也就是在内连接查询中,只有满足条件的元组才能出现在结果关系中。
例如:要查询每个已经选课的学生的情况,查询语句为
SELECT*
FROM学生表INNER JOIN选课表ON学生表.学号=选课表.学号
分类:
根据比较方式分为:
1)等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。
2)不等连接:在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
3)自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。
三、自连接
如果在一个连接查询中,涉及到的两个表都是同一个表,这种查询就称为自连接查询。同一张表在FROM字句中多次出现,为了区别该表的每一次出现,需要为表定义一个别名。自连接是一种特殊的内连接,它是指相互连接的表在物理上为同一张表,但可以在逻辑上分为两张表。
例如:要求检索出学号为20210的学生的同班同学的信息,查询语句为
SELECT学生表.*
FROM学生表JOIN学生表AS学生表1ON学生表.班级=学生表1.班级
WHERE学生表1.学号='20210'
四、外连接
内连接的查询结果都是满足连接条件的元组。但有时我们也希望输出那些不满足连接条件的元组信息。比如,我们想知道每个学生的选课情况,包括已经选课的学生(这部分学生的学号在学生表中有,在选课表中也有,是满足连接条件的),也包括没有选课的学生(这部分学生的学号在学生表中有,但在选课表中没有,不满足连接条件),这时就需要使用外连接。外连接是只限制一张表中的数据必须满足连接条件,而另一张表中的数据可以不满足连接条件的连接方式。
3种外连接:
1)左外连接(LEFTOUTER JOIN)
如果在连接查询中,连接管子左端的表中所有的元组都列出来,并且能在右端的表中找到匹配的元组,那么连接成功。如果在右端的表中,没能找到匹配的元组,那么对应的元组是空值(NULL)。这时,查询语句使用关键字LEFT OUTERJOIN,也就是说,左外连接的含义是限制连接关键字右端的表中的数据必须满足连接条件,而不关左端的表中的数据是否满足连接条件,均输出左端表中的内容。
例如:要查询所有学生的选课情况,包括已经选课的和还没有选课的学生,查询语句为
SELECT学生表.学号,姓名,班级,课程号,成绩
FROM学生表LEFT OUTER JOIN选课表ON学生表.学号=选课表.学号
左外连接查询中左端表中的所有元组的信息都得到了保留。
2)右外连接(RIGHTOUTERJOIN)
右外连接与左外连接类似,只是右端表中的所有元组都列出,限制左端表的数据必须满足连接条件,而不管右端表中的数据是否满足连接条件,均输出表中的内容。
例如:同上例内容,查询语句为
SELECT学生表.学号,姓名,班级,课程号,成绩
FROM学生表RIGHTOUTERJOIN选课表ON学生表.学号=选课表.学号
右外连接查询中右端表中的所有元组的信息都得到了保留。
3)全外连接(FULL OUTER JOIN)
全外连接查询的特点是左、右两端表中的元组都输出,如果没能找到匹配的元组,就使用NULL来代替。
例如:同左外连接例子内容,查询语句为
SELECT学生表.学号,姓名,班级,课程号,成绩
FROM学生表FULL OUTER JOIN选课表ON学生表.学号=选课表.学号
全外连接查询中所有表中的元组信息都得到了保留。
五、应用示例
2 以MySql为例。在MySQL数据库中建立两张数据表,并分别插入一些数据。
4 脚本如下:
5 drop table table1;
6 CREATE TABLE `andrew`.`table1`
7 (
8 `name` VARCHAR(32) NOT NULL,
9 `city` VARCHAR(32) NOT NULL
10 )
11 ENGINE = MyISAM;
12 insert into TABLE1(name, city) values ('Person A', 'BJ');
13 insert into TABLE1(name, city) values ('Person B', 'BJ');
14 insert into TABLE1(name, city) values ('Person C', 'SH');
15 insert into TABLE1(name, city) values ('Person D', 'SZ');
16 commit;
17 drop table table2;
18 CREATE TABLE `andrew`.`table2`
19 (
20 `name` VARCHAR(32) NOT NULL,
21 `city` VARCHAR(32) NOT NULL
22 )
23 ENGINE = MyISAM;
24 insert into TABLE2(name, city) values ('Person W', 'BJ');
25 insert into TABLE2(name, city) values ('Person X', 'SH');
26 insert into TABLE2(name, city) values ('Person Y', 'SH');
27 insert into TABLE2(name, city) values ('Person Z', 'NJ');
28 commit;
29 1. 外连接 – 左连接结果
30 table1居左,故谓之左连接。这种情况下,以table1为主,即table1中的所有记录均会被列出。有一下三种情况:
31 a. 对于table1中的每一条记录对应的城市如果在table2中也恰好存在而且刚好只有一条,那么就会在
32 返回的结果中形成一条新的记录。如上面Person A和Person B对应的情况。
33 b. 对于table1中的每一条记录对应的城市如果在table2中也恰好存在而且有N条,那么就会在返回的结果中形成N条新的记录。如上面的Person C对应的情况。
34 c. 对于table1中的每一条记录对应的城市如果在table2中不存在,那么就会在返回的结果中形成一条
35 条新的记录,且该记录的右边全部NULL。如上面的Person D对应的情况。
36 不符合上面三条规则的记录不会被列出。
37 2. 外连接 – 右连接结果
38 table2居右,故谓之右连接。这种情况下,以table2为主,即table2中的所有记录均会被列出。有一下三种情况:
39 a. 对于table2中的每一条记录对应的城市如果在table1中也恰好存在而且刚好只有一条,那么就会在
40 返回的结果中形成一条新的记录。如上面Person X和Person Y对应的情况。
41 b. 对于table2中的每一条记录对应的城市如果在table1中也恰好存在而且有N条,那么就会在返回的结果中形成N条新的记录。如上面的Person W对应的情况。
42 c. 对于table2中的每一条记录对应的城市如果在table1中不存在,那么就会在返回的结果中形成一条
43 条新的记录,且该记录的左边全部NULL。如上面的Person Z对应的情况。
44 不符合上面三条规则的记录不会被列出。
45 3. 内连接
46 内连接的数据记录中,不会存在字段为NULL的情况。可以简单地认为,内链接的结果就是在左连接或者右连接的结果中剔除存在字段为NULL的记录后所得到的结果。
甚至可以认为,如果两个表中仅分别剩下内连接运算后所得的数据记录,如table1中只有Person A、Person B和Person C,table2中只有Person W、Person X和Person Y,
那么这两个表的之间的左连接和右连接的返回的结果是一样的。
47 注意:select * from table1 a inner join table2 b on a.city = b.city 和select * from table1 a join table2 b on a.city = b.city 的效果是一样的,
即如果join的左边没有诸如left、right或者inner这样的关键字时,缺省的是内连接。另,MySQL不支持full join。