2012-03-21 71 views
0

考慮三個表:項目之一,這些項目上的標籤之一,以及第三個將標籤ID映射到標籤名稱。Mysql加入項目和標籤

項目:

ITEM ID ITEM NAME 
------------------- 
1   Item 1 
2   Item 2 
3   Item 3 

標籤:

ID TAG ID ITEM ID 
1  1  1 
2  2  1 
3  3  1 
4  1  2 
5  1  3 

標籤名稱:

TAG ID TAG NAME 
1  TAG_A 
2  TAG B 
3  TAG C 

因此,只有第1項有標籤TAG_A,TAG_B和TAG_C。

你如何做一個選擇檢索所有具有TAG_A,TAG_B和TAG_C的項目而不做3個INNER JOIN?換句話說,我知道我可以做一個選擇,並說

INNER JOIN item_tags pt4 ON pt4.item_id = p.item_id AND pt4.tag_id = 1 
INNER JOIN item_tags pt13 ON pt13.item_id = p.item_id AND pt13.tag_id = 2 
INNER JOIN item_tags pt19 ON pt19.item_id = p.item_id AND pt19.tag_id = 3 

但這是效率低下,對吧?

怎麼樣一個子查詢,像

SELECT * FROM項WHERE ... AND ITEM_ID IN(SELECT ITEM_ID FROM item_tags WHERE TAG_ID IN(1,2,3))

(這確切的查詢將不起作用 - 這是一個OR標籤,但這是我要去的。)

+2

那你試試,沒有工作? – 2012-03-21 01:06:52

+1

您是否正在查找返回包含所有標籤或僅具有指定標籤的項目的查詢? – iWantSimpleLife 2012-03-21 01:07:17

+0

@iWantSimpleLife只是三個指定的標籤TAG_A,TAG_B和TAG_C。 – 2012-03-21 01:10:46

回答

2

嘗試此查詢 -

SELECT t.item_id FROM tags t 
    JOIN tag_names tn 
    ON t.tag_id = tn.tag_id 
GROUP BY 
    t.item_id 
HAVING 
    COUNT(DISTINCT t.tag_id) = (SELECT COUNT(*) FROM tag_names) 
+0

我有名稱爲id映射完成,所以我只是使用你有什麼作爲我的子查詢 - SELECT t.item_id FROM tags t GROUP BY t.item_id HAVING COUNT(DISTICT t.tag_id)= <標籤數量的計數>。 GROUP BY和COUNT是我一直在尋找的。 – 2012-03-22 14:52:51

0

第一個查詢(別名sqlvars)創建一個@NumTags變量,標籤名稱中有多少個標籤表,所以它不需要在每個符合條件的標籤組上進行。

第二個查詢(別名HasAllTags)獲取項目,按itemid分組,其總計數等於@NumTags。

最後,HasAllTags加入到項目中以提取數據。

select 
     I.* 
    from 
     (select @NumTags := (select count(*) from TagName)) sqlvars, 
     (select t.ItemID 
      from Tags t 
      group by t.ItemID 
      having count(*) = @NumTags) HasAllTags 
     JOIN Items I 
      on HasAllTags.ItemID = I.ItemID