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
數據倉庫與數據挖掘培訓視頻教程
From:http://tw.wingwit.com/Article/program/SQL/201311/16472.html