Join

多對多關係

  • October 28, 2012

我正在研究書籍數據庫。除其他外,我有以下兩個表(問題有點簡化):

tblBook: ID, Title
tblPerson: ID, Name

請注意,該tblPerson表包含作者、翻譯者和編輯者(不僅是作者)。

很明顯,這兩個表之間是多對多的關係,所以我也有如下聯結表:

tblBookAuthorJunction
tblBookTranslatorJunction
tblBookEditorJunction

但是,在加入表以選擇所有角色時,我遇到了一個問題:如何創建查詢以使表看起來像:

BookTitle AuthorName TranslatorName EditorName

這是可能嗎?我的查詢應該是什麼樣的?

**編輯:**您可以為 RDBMS 假設 SQLite。


更新

到目前為止,有兩個包含查詢的答案。我想將這些答案與可能發現此資訊有價值的其他人進行比較…請注意,聯結表的名稱與問題中的名稱略有不同。而且,是的,我知道,測試數據很無聊。

答案 1

我自己的答案中的查詢如下:

SELECT B.BookTitle, P1.PersonName, P2.PersonName, P3.PersonName
FROM tblBook B
LEFT JOIN tblBookAuthor A ON B.BookID = A.BookID
LEFT JOIN tblPerson P1 ON A.AuthorID = P1.PersonID
LEFT JOIN tblBookTranslator T ON B.BookID = T.BookID
LEFT JOIN tblPerson P2 ON T.TranslatorID = P2.PersonID
LEFT JOIN tblBookEditor E ON B.BookID = E.BookID
LEFT JOIN tblPerson P3 ON E.EditorID = P3.PersonID

此查詢的輸出如下所示:

在此處輸入圖像描述

答案 2

Erwin Brandstetter 的答案中的查詢如下(稍作修改以適應測試數據庫):

SELECT B.BookTitle, BA.Authors, BT.Translators, BE.Editors
FROM tblBook B
LEFT JOIN (
   SELECT  J.BookID, group_concat(P.PersonName, ', ') AS Authors
   FROM    tblBookAuthor J
   JOIN    tblPerson P ON J.AuthorID = P.PersonID
   GROUP   BY J.BookID
   ) AS BA ON BA.BookID = B.BookID

LEFT JOIN (
   SELECT  J.BookID, group_concat(P.PersonName, ', ') AS Translators
   FROM    tblBookTranslator J
   JOIN    tblPerson P ON J.TranslatorID = P.PersonID
   GROUP   BY J.BookID
   ) AS BT ON BT.BookID = B.BookID

LEFT JOIN (
   SELECT  J.BookID, group_concat(P.PersonName, ', ') AS Editors
   FROM    tblBookEditor J
   JOIN      tblPerson P ON J.EditorID = P.PersonID
   GROUP   BY J.BookID
   ) AS BE ON BE.BookID = B.BookID

此查詢的輸出如下所示:

在此處輸入圖像描述

如果每本書可以有多個作者/編輯/翻譯 - 就像在現實生活中一樣,並且就像您的關係設計所暗示的那樣,那麼帶有普通LEFT JOINs 的現有答案將產生不正確的結果。如果任何一本書的每個角色最多可以有一個人,那麼您可以從根本上簡化您的設計:不需要聯結表,只需表中的一個外鍵列Books

您需要聚合作者、翻譯和編輯。Books您可以在連接所有行(並生成多個結果行)之後執行此操作,但在子查詢中聚合然後連接到表應該更有效

SELECT B.BookTitle, BA.Authors, BT.Translators, BE.Editors
FROM   tblBook B
LEFT JOIN (
   SELECT  J.BookID, group_concat(P.Name, ', ') AS Authors
   FROM    tblBookAuthorJunction J
   JOIN    tblPerson P ON J.AuthorID = P.PersonID
   GROUP   BY J.BookID
   ) AS BA ON BA.BookID = B.ID

LEFT JOIN (
   SELECT  J.BookID, group_concat(P.Name, ', ') AS Translators
   FROM    tblBookTranslatorJunction J
   JOIN    tblPerson P ON J.TranslatorID = P.PersonID
   GROUP   BY J.BookID
   ) AS BT ON BT.BookID = B.ID

LEFT JOIN (
   SELECT  J.BookID, group_concat(P.Name, ', ') AS Editors
   FROM    tblBookEditorJunction J
   JOIN    tblPerson P ON J.EditorID = P.PersonID
   GROUP   BY J.BookID
   ) AS BE ON BE.BookID = B.ID
WHERE  B.ID = 123

在大多數 RDBMS 中,如果您也添加子查詢,它會更快WHERE BookID = 123

引用自:https://dba.stackexchange.com/questions/27736