N路INNER JOIN
当两个表之间不存在直接的关系时该怎么联接这两个表呢?在这种情况下联接操作需要涉及更多的表!在上一小节INNER JOIN的练习中已经演示了一个实际的例子
例如有时我们需要列出所有的图书以及各图书相应的作者请注意在数据库中一本图书并不知道它的作者信息在哪里(即在BOOKS表的数据行中并没有关于该图书作者的信息)而作者信息的记录同样也不知道该作者编写的图书的信息在什么地方但是在数据库中有一个BOOKS_AUTHORS表它包含了这样的知识哪一本图书是哪一个作者编写的以及哪一个作者编写了哪些图书BOOKS_AUTHORS表中的每一行都包含了一个BOOKS表的外键和一个AUTHORS表的外键如果一本图书是由多个作者编写的那么该BOOKS_AUTHORS表中就具有多行记录每一行包含了相同的图书ID和不同的作者ID反之亦然(对于任何一个编写了多本图书的作者)
由于BOOKS表中的数据行没有对于AUTHORS表的外键AUTHORS表的数据行也没有对于BOOKS表的外键因此没有办法直接将这两个表联接起来但是可以将这两个表联接到BOOKS_AUTHORS表
SELECT
booksbk_title AS Book
authorsau_last_name AS Author
FROM books INNERJOIN books_authors
ON booksbk_id = books_authorsbk_id
INNER JOIN authors
ON authorsau_id = books_authorsau_id;
联接的结果如表所示正如我们所期望的如果一本书的作者超过一位那么有多少个作者在列表中就会列出多少条记录
表 列出图书及其相应的作者
在结果集中可能会出现重复的图书名称也可能会出现重复的作者名字但是图书名称与作者名字的每一个组合在结果集中仅仅只会出现一次
接下来分析一下该查询返回的数据集背后的逻辑下面是该查询的第一部分SELECT字段列表
SELECT
booksbk_title AS Book
authorsau_last_name AS Author
该字段列表并没有什么神奇它告诉查询引擎我们感兴趣的字段并为字段列表中的列定义一个比默认名称更加可爱的列名(别名)注意虽然查询了多个表但并非一定要从每一个表中都获取数据在本例中只需要一些来自BOOKS表的字段和一些来自AUTHORS表的字段而并不需要获取BOOKS_AUTHORS表中的字段
FROM books INNER JOIN books_authors
ON booksbk_id = books_authorsbk_id
上面的子句定义了第一个INNER JOIN指定了要联接哪两个表以及如何联接这两个表在本例中联接条件是BOOKS表中的BK_ID列的值必须与BOOKS_AUTHORS表中BK_ID列的值相等(两个表中的列名不一定要相同但是相同的列名使用起来会比较方便)
INNER JOIN authors ON authorsau_id = books_authorsau_id
上面的子句定义了第二个INNER JOIN请注意它与第一个INNER JOIN子句的不同在第一个INNER JOIN子句中指定了两个表books INNER JOIN books_authors但在第二个INNERJOIN中仅仅指定了一个表INNER JOIN authors这里并不需要指定其他的表它已经被绑定到之前指定的两个表中的一个并且行匹配规则将指定它与哪一个表进行联接(在本例中行匹配规则是AUTHORS表中AU_ID列的值与BOOKS_AUTHORS表中AU_ID列的值相等)
运行该查询后如果BOOKS表中包含在BOOKS_AUTHORS表中没有记录的图书则结果集中不会包含这样的图书如果AUTHORS表中的任何作者在BOOKS_AUTHORS表中并不存在则结果集中也不会包含这样的作者
试一试使用四路联接
如何查询位于书柜的顶层书架中名称以SQL开头的图书以及图书的作者呢?当然这需要联接LOCATION表BOOKS表和AUTHORS表由于在图书与图书的作者之间是一个多对多关系因此必须包含BOOKS_AUTHORS表作为中间表以解决多对多关系的复杂性问题下面将使用Microsoft SQL Server来演示联接的功能在本书所讨论的其他任何一种RDBMS中下面的脚本无须修改都能正常运行下面让我们来实践一下吧
() 打开Microsoft SQL Server Management Studio使用Windows身份验证连接到数据库
() 单击左上角的New Query按钮输入下面的SQL查询
SELECT
au_last_name AS author
bk_title AS title
FROM books bk INNER JOIN books_authors ba
ON bkbk_id = babk_id
INNER JOIN authors au
ON baau_id = auau_id
INNER JOIN location loc
ON bkbk_id = locfk_bk_loc
WHERE locloc_shelf =
AND bkbk_title LIKE SQL%
() 单击工具栏上的Execute按钮观察返回的结果
author title
Kriegel SQL Bible
Trukhnov SQL Bible
Kriegel SQL Functions: Programmers Reference
Jones SQL Functions: Programmers Reference
Stephens SQL Functions: Programmers Reference
Plew SQL Functions: Programmers Reference
Garrett SQL Functions: Programmers Reference
( row(s) affected)
示例说明
在之前的例子中联接的价值在于尽量减少选取的记录直到数据集完全符合指定的筛选标准在本例中数据库引擎将从按照JOIN语句联接的所有表对中匹配记录(即BOOKS/BOOKS_AUTHORSBOOKS_AUTHORS/AUTHORS和BOOKS/LOCATION表对)最后再应用筛选条件减小数据集仅仅返回满足条件LOC_SHELF = 和BK_TITLE以SQL开头的记录(请回忆一下带有LIKE谓词的匹配模式)
返回目录SQL实战新手入门
编辑推荐
Oracle索引技术
高性能MySQL
数据仓库与数据挖掘培训视频教程