Join
多對多關係
我正在研究書籍數據庫。除其他外,我有以下兩個表(問題有點簡化):
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 JOIN
s 的現有答案將產生不正確的結果。如果任何一本書的每個角色最多可以有一個人,那麼您可以從根本上簡化您的設計:不需要聯結表,只需表中的一個外鍵列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
。