4.2.5 连接查询

4.2.5 连接查询

连接是关系数据库模型的主要特点。连接查询是关系数据库中最主要的查询,主要包括内连接、外连接等。通过连接运算符可以实现多个表查询。在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当查询数据时,通过连接操作查询出存放在多个表中的不同实体的信息。当两个或多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。本节将介绍多表之间的内连接查询、外连接查询及复合条件连接查询。

1.内连接查询

内连接(inner join)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行,组合成新的记录,也就是说,在内连接查询中,只有满足条件的记录才能在结果关系中显示。

【例4.55】在employees表和departments表之间使用内连接查询。

查询之前,查看两个表的结构:

由结果可以看到,employees表和departments表中都有相同数据类型相同含义的字段deptno和dno,两个表通过deptno、dno字段建立联系。接下来从employees表中查询ename、esal字段,从departments表中查询dname。

SQL语句及执行效果如下:

在这里,select语句与前面所介绍的最大的差别是:select后面指定的字段分别属于两个不同的表,ename、esal在表employees中,而dname在表departments中;同时,from子句列出了两个表employees和departments。where子句在这里作为过滤条件,指明只有两个表中的deptno、dno字段值相等的时候才符合连接查询的条件。由返回的结果可以看到,显示的记录是由两个表中的不同字段值组成的新记录。

提示:因为emp l oyees表和depa r tmen t s表中有数据类型及含义相同的字段dep tno、dno。假如两个表中的关联字段名字相同,都为dno,那么在比较的时候,需要完全限定表名(格式为:表名.字段名)。如果只给出dno,MySQL将不知道指的是哪一个,并返回错误信息。

下面的内连接查询语句返回与前面完全相同的结果。

【例4.56】在employees表和departments表之间使用inner join语法进行内连接查询。

SQL语句及执行效果如下:

在这里的查询语句中,两个表之间的关系通过inner join指定。使用这种语法的时候,连接的条件使用on子句给出,而不是where。on和where后面指定的条件相同。在on子句后面字段名前添加了表名,因为这两个表中的字段名不同,所以表名可以省略。

提示:使用whe r e子句定义连接条件比较简单明了,而inne r j oin语法是ANSI SQL的标准规范,使用inner j oin连接语法能够确保不会忘记两表连接条件,而且whe r e子句在某些时候会影响查询的性能。

如果在一个连接查询中,涉及的两个表都是同一个表,这种查询称为自连接查询。自连接是一种特殊的内连接,它是指相互连接的表在物理上为同一张表,但可以在逻辑上分为两张表。

【例4.57】查询出employee表中所有员工的姓名及其直接上级的姓名。

SQL语句及执行效果如下:

此处查询的两个表是同一张表,为了防止产生二义性,对表使用了别名(表的别名定义与字段的别名定义方法相同)。employees表第一次出现代表员工信息时,其别名为“e”,第二次出现代表员工直接上级的相关信息时,其别名为“w”,使用select语句返回字段时,明确指出返回以“e”和“w”为前缀的字段的全名。where连接两个表,返回所需数据。

2.外连接查询

连接查询将查询多个表中相关联的行,内连接时,返回查询结果集中仅是符合查询条件和连接条件的行。但有时候需要包含没有关联的行中数据,即返回查询结果集中不仅包含符合连接条件的行,而且还包括左表(左外连接或左连接)、右表(右外连接或右连接)或两个边接表(全外连接)中的所有数据行。外连接分为左外连接和右外连接。

•left join(左连接):返回包括左表中的所有记录和右表中连接字段值相等的记录。

•right join(右连接):返回包括右表中的所有记录和左表中连接字段值相等的记录。

(1)left join左连接

左连接的结果包括left outer join(outer可以省略)子句中指定的左表的所有行,而不仅仅是连接字段所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表字段均为空值。

【例4.58】在employees表和departments表中,查询部门名称及其员工的名字、职位、工资,包括没有员工的部门也要显示出来。

SQL语句及执行效果如下:

结果显示了19条记录,后勤部没有员工信息,所以只有部门名称显示出来了,员工的ename、ejob、esal都为null。因此总结出左外连接中左表的数据全都显示,右表按照连接条件显示。

(2)right join右连接

右连接的结果包括right outer join(outer可以省略)子句中指定的右表的所有行,而不仅仅是连接字段所匹配的行。如果右表的某行在左表中没有匹配行,则在相关联的结果行中左表的所有选择列表字段均为空值。

【例4.59】在employees表和departments表中,查询部门名称及其员工的名字、职位、工资,包括没有分配部门的员工也要显示出来。

SQL语句及执行效果如下:

结果显示了20条记录,栾凯、程程这两位员工还没有分配部门,所以他们的部门名称dname字段为null。因此总结出右外连接中右表的数据全都显示,左表按照连接条件显示。

(3)笛卡尔积(交叉连接)

交叉连接返回左表中的所有行,左表中的每一行与右表中的所有行组合。交叉连接也称作笛卡尔积。在MySQL中,交叉连接可以使用cross join或者省略cross即join,或者使用‘,’。

【例4.60】查询employees和departments中eno、ename、deptno、dno、dname五个字段的两表交叉连接的结果。

SQL语句及执行效果如下:

由结果可以看到,employees中有20条记录,departments表中有6条记录,这两个表交叉连接查询之后是120条记录。

例4.60的代码等同于“select eno,ename,deptno,dno,dname from employees join departments;”和“select eno,ename,deptno,dno,dname from employees,departments;”这两段代码。

由于交叉连接返回的结果为被连接的两个数据表的乘积,因此,当有where、on或using条件的时候,一般不建议使用,因为当数据表项目太多的时候,会非常慢。一般使用left[outer]join或者right[outer]join。

3.复合条件连接查询

复合条件连接查询是在连接查询的过程中,通过添加过滤条件,限制查询的结果,使查询的结果更加准确。

【例4.61】在employees表和departments表中,使用inner join语法查询employees表中deptno为4的员工的eno、ename、ejob、dname。

SQL语句及执行效果如下:

结果显示,在连接查询时,指定查询部门编号deptno为4的员工信息。添加了过滤条件之后,返回的结果将会变少,因此返回结果只有4条记录。

【例4.62】在employees表和departments表中,使用inner join语法进行内连接查询,显示部门名称为“销售部”的员工信息,并对查询结果按eno降序排序。

SQL语句及执行效果如下:

由结果可以看到,内连接查询的结果按照eno字段进行了降序排序。

实训:

①查询雇用日期早于其直接上级的所有员工信息。

②查询部门名称、地址及部门对应的员工姓名、职位、工资、奖金,同时列出那些没有部门的员工信息。

③查询在部门“财务部”工作的员工的姓名,假定不知道财务部的部门编号。