2012-08-13 80 views
1

我有一個客戶,要我做一個標記系統。我有三個表格:items,tagsitem_tag_assoc - 最後一個僅用於關聯item_ids和tag_ids。以下是我遇到的問題:MySQL複雜的加入多個包含和排除

如果用戶請求包含標籤[1,2,3]和排除標籤[4,5,6],則結果應該是所有具有每個標籤的項目[ 1,2,3](不只是一個)和NO標籤[4,5,6]。我如何編寫查詢來完成此操作?

我研究了足夠找出內部連接的標籤包括:

SELECT i.item_id, i.item_title FROM items AS i INNER JOIN tag_item_assoc AS tia1 ON (tia1.item_id = i.item_id AND tia1.tag_id = 1)

...和你想僅包含在同一個內鏈模式加入儘可能多的標籤。它可能有點笨重,但用戶在移動之前不會選擇超過4或5個標籤,因此它可以。

我真的很希望我能排除以同樣的方式,和一切包裝成一個查詢:

INNER JOIN tag_item_assoc AS tia2 ON (tia2.item_id = i.item_id AND tia2.tag_id!= 2)

但它很快變得明顯,是行不通的。我讀了幾篇文章,說LEFT OUTER JOIN s可以讓我排除,但我不明白,主要是因爲流浪WHERE條款。 LEFT OUTER JOIN s和INNER JOIN s的任何排列我嘗試了或者產生了一個錯誤或非常混亂的結果。

說了這麼多 - 這裏有人知道我可以做到這一點嗎?我很抱歉沒有任何有用的代碼示例提供。如果INNER JOIN是一個障礙,我可以從頭開始 - 我只需要一種方法來同時完成多個關聯包含和排除。預先感謝您的幫助和專業知識!

+0

可能與標籤IN(1,2,3) – 2012-08-13 07:25:45

+0

不一樣 - IN(1,2,3)將與標籤[1],[1,3]等項目相匹配,我需要僅在集合[1,2,3]中找到具有EVERY標籤的項目。感謝您的迴應,希望澄清! – CodeMoose 2012-08-13 07:47:36

+0

如果您能提供相同的樣品數據和樣品輸出,這將會很有幫助。 – Omesh 2012-08-13 07:50:23

回答

0

找到了答案。而不是增加INNER JOIN就像這樣的:

INNER JOIN tag_item_assoc AS tia2 ON (tia2.item_id = i.item_id AND tia2.tag_id!= 2)

我加了一個子查詢與一個內部聯接:

WHERE i.item_id NOT IN (SELECT i.item_id FROM items AS s INNER JOIN tag_item_assoc AS tia1 ON (tia1.item_id = i.item_id AND tia1.tag_id IN (4, 5, 6)))

子查詢創建了一個集合中的所有item S的那有[4,5,6]中的任何標籤,並且WHERE i.iten_id NOT IN消除了與該組相匹配的任何記錄。

感謝大家的努力!希望這會幫助路上的人。

0

您需要的記錄實例數匹配您的標籤的數量:

SELECT a.item_id -- , add other columns here 
FROM items a 
      INNER JOIN item_tag_assoc b 
      ON a.item_id = b.item_id 
WHERE b.tag_id IN (1, 2, 3) AND 
     b.tag_id NOT IN (4, 5, 6) 
GROUP BY a.item_id 
HAVING COUNT(a.item_id) = 3 
+0

感謝您的回答,這比我想出的解決方案更加優雅。有沒有一種方法可以用類似的方法排除標籤? – CodeMoose 2012-08-13 07:52:29

+0

@CodeMoose現在有效嗎? – 2012-08-13 08:05:39

+0

不完全 - (1,2,3)很好,但(4,5,6)部分對我來說似乎不對。我們是不是隻包括我們試圖排除的那一套? – CodeMoose 2012-08-13 08:15:35

0
SELECT a.* 
FROM items a 
    INNER JOIN item_tag_assoc b 
     ON a.item_id = b.item_id 
    INNER JOIN tags c 
     ON a.tag_id = c.tag_id 
WHERE c.tag_id IN(1) AND 
     c.tag_id IN(2) AND 
     c.tag_id IN(3) AND 
     c.tag_id NOT IN (4) AND 
     c.tag_id NOT IN (5) AND 
     c.tag_id NOT IN (6) ; 
+0

您是否嘗試過此查詢? – Imdad 2012-08-13 10:01:46

+0

我做到了 - 仍然不是我要找的東西。感謝您的努力! – CodeMoose 2012-08-13 18:17:31