
7.4 连接查询
连接是关系数据库模型的主要特点。连接查询是关系数据库中最主要的查询,主要包括内连接、外连接等。通过连接运算符可以实现多个表查询。在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当查询数据时,通过连接操作查询出存放在多个表中的不同实体的信息。当两个或多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。本节将介绍多表之间的内连接查询、外连接查询以及复合条件连接查询。
7.4.1 内连接查询
内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行,组合成新的记录。也就是说,在内连接查询中,只有满足条件的记录才能出现在结果关系中。
为了演示的需要,首先创建数据表suppliers, SQL语句如下:

插入需要演示的数据,SQL语句如下:

【例7.46】在fruits表和suppliers表之间使用内连接查询。
查询之前,查看两个表的结构:

由结果可以看到,fruits表和suppliers表中有相同数据类型的字段s_id,两个表通过s_id字段建立联系。接下来从fruits表中查询f_name、f_price字段,从suppliers表中查询s_id、s_name字段,SQL语句如下:

在这里,SELECT语句与前面介绍的一个最大的差别是:SELECT后面指定的列分别属于两个不同的表,(f_name,f_price)在表fruits中,而另外两个字段在表supplies中;同时FROM子句列出了两个表fruits和suppliers。WHERE子句在这里作为过滤条件,指明只有两个表中的s_id字段值相等的时候才符合连接查询的条件。返回的结果可以看到,显示的记录是由两个表中的不同列值组成的新记录。
提示
因为fruits表和suppliers表中有相同的字段s_id,因此在比较的时候,需要完全限定表名(格式为“表名.列名”),如果只给出s_id, MySQL将不知道指的是哪一个表,并返回错误信息。
下面的内连接查询语句返回与前面完全相同的结果。
【例7.47】在fruits表和suppliers表之间使用INNER JOIN语法进行内连接查询,SQL语句如下:

在这里的查询语句中,两个表之间的关系通过INNER JOIN指定。使用这种语法的时候,连接的条件使用ON子句给出而不是WHERE, ON和WHERE后面指定的条件相同。
提示
使用WHERE子句定义连接条件比较简单明了,而INNER JOIN语法是ANSI SQL的标准规范,使用INNER JOIN连接语法能够确保不会忘记连接条件,而且WHERE子句在某些时候会影响查询的性能。
如果在一个连接查询中涉及的两个表是同一个表,这种查询称为自连接查询。自连接是一种特殊的内连接,它是指相互连接的表在物理上为同一个表,但可以在逻辑上分为两个表。
【例7.48】查询f_id=‘a1‘的水果供应商提供的水果种类,SQL语句如下:

此处查询的两个表是相同的表,为了防止产生二义性,对表使用了别名,ftuits表第1次出现的别名为f1,第2次出现的别名为f2,使用SELECT语句返回列时明确指出返回以f1为前缀的列的全名,WHERE连接两个表,并按照第2个表的f_id对数据进行过滤,返回所需的数据。
7.4.2 外连接查询
外连接查询将查询多个表中相关联的行,内连接时,返回查询结果集合中的仅是符合查询条件和连接条件的行。但有时需要包含没有关联的行中的数据,即返回查询结果集合中不仅包含符合连接条件的行,还包括左表(左外连接或左连接)、右表(右外连接或右连接)或两个边接表(全外连接)中所有的数据行。外连接分为左外连接(或左连接)和右外连接或(右连接):
·LEFT JOIN(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录。
·RIGHT JOIN(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。
1.LEFT JOIN(左连接)
左连接的结果包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。若左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值。
首先创建表orders, SQL语句如下:

插入需要演示的数据,SQL语句如下:

【例7.49】在customers表和orders表中,查询所有客户,包括没有订单的客户,SQL语句如下:

结果显示了5条记录,ID等于10002的客户目前并没有下订单,所以对应的orders表中并没有该客户的订单信息,这条记录只取出了customers表中相应的值,而从orders表中取出的值为空值(NULL)。
2.RIGHT JOIN(右连接)
右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,那么左表将返回空值。
【例7.50】在customers表和orders表中,查询所有订单,包括没有客户的订单,SQL语句如下:

结果显示了5条记录,订单号等于30004的订单的客户可能由于某种原因取消了该订单,对应的customers表中并没有该客户的信息,所以这条记录只取出了ordes表中相应的值,而从customers表中取出的值为空值(NULL)。
7.4.3 复合条件连接查询
复合条件连接查询是在连接查询的过程中通过添加过滤条件限制查询的结果,使查询的结果更加准确。
【例7.51】在customers表和orders表中,使用INNER JOIN语法查询customers表中ID为10001的客户的订单信息,SQL语句如下:

结果显示,在连接查询时指定查询客户ID为10001的订单信息,添加了过滤条件之后返回的结果将会变少,因此返回结果只有两条记录。
使用连接查询并对查询的结果进行排序。
【例7.52】在fruits表和suppliers表之间使用INNER JOIN语法进行内连接查询,并对查询结果排序,SQL语句如下:

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