假設這些表:
- 帖子ID,作者,日期,內容
- 標籤ID,名稱
- PostTags :post_id,tag_id
最後一個表通常被稱爲連接表,並促進了文章和標籤之間的多對多關係。
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'sql'
基本上,認爲許多一對多的關係,兩個一對多關係的,因爲這是他們如何在正常的RDBMS實現。所以上面的查詢有一個從Posts到PostTag的一對多連接,另一個從Tags到PostTag。
我創建的PostTags表具有複合主鍵,即(post_id, tag_id)
。這種組合將是獨一無二的。許多冷遇組合鍵,因此您會經常看到有人創建一個主鍵列:
- PostTags:ID,POST_ID,TAG_ID
兩種方法是罰款。這在很大程度上是一個哲學上的差異。
更新:,如果你想選擇所有具有特定標籤,所有的標籤這些帖子有那麼帖子:
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE p.id IN
(SELECT post_id
FROM PostTags pt
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'xyz')
另一種方式來做到這一點:
SELECT p.*
FROM posts p
JOIN posttags pt ON p.id = pt.post_id
JOIN tags t ON pt.tag_id = t.id
WHERE EXISTS
(SELECT post_id
FROM PostTags pt
JOIN tags t ON pt.tag_id = t.id
WHERE t.name = 'xyz'
AND pt.post_id = p.id)
哪個性能更好將需要測試,並可能因數據庫供應商和版本而異。一個好的優化器(如Oracle)可能會優化它們以執行相同的操作。其他人可能不會。
現在,這將讓你回行這樣的:
Post 1, tag 1
Post 1, tag 2
Post 3, tag 2
Post 3, tag 3
所以你需要把它們混合起來,最好是在應用程序邏輯,而不是SQL。一些關係數據庫管理系統有這種類型的供應商特定的擴展,比如MySQL的GROUP_CONCAT()
函數。
查看更新.... – cletus 2010-08-03 15:51:48
鑑於所選答案似乎是一個SQL解決方案而不是DQL,這個問題的標題不應該從DQL更改爲SQL嗎?我來到這裏尋找一種方法來完成多對多的DQL查詢,但這裏沒有任何內容。 – 2012-03-29 20:50:47