2010-08-03 261 views
2

如果我在帖子和標籤之間存在多對多關係,如何選擇包含特定標籤的帖子?SQL如何查詢多對多關係

更新:

我遇到的問題是,因爲在那裏tag.name = 'xxx',只有標籤被選中。我想要的是選擇具有指定標籤的所有帖子,tgt與他們的所有標籤,例如。

Post 1 -> tag1, tag2 
Post 2 -> tag1, tag3 
Post 3 -> tag2, tag3 

目前我所得到的是

Post 1 -> tag2 // missing tag1 
Post 3 -> tag2 // missing tag3 
+0

查看更新.... – cletus 2010-08-03 15:51:48

+5

鑑於所選答案似乎是一個SQL解決方案而不是DQL,這個問題的標題不應該從DQL更改爲SQL嗎?我來到這裏尋找一種方法來完成多對多的DQL查詢,但這裏沒有任何內容。 – 2012-03-29 20:50:47

回答

4

假設這些表:

  • 帖子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()函數。

+0

我只是'選擇帖子,標籤從應用程序\模型\發佈帖子INNER JOIN post.tags tags' b4我看到這篇文章,它似乎工作。沒有標籤名稱tho。你和我的有什麼不同嗎? – 2010-08-03 10:38:28

+0

我還發現,由於where子句,只有在那裏指定的標籤被選中。我想用該標籤獲取帖子。但對於匹配的帖子,我想要所有,而不僅僅是指定的標籤。也許我在子查詢上工作 – 2010-08-03 10:45:02

+0

@jiewmeng我不明白你的問題。 – cletus 2010-08-03 11:30:08