Mysql JOIN用于项目和标签

时间:2012-03-21 01:04:07

标签: mysql join

考虑三个表:一个项目,一个是这些项目上的标签,第三个是将标签ID映射到标签名称。

项目:

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 items WHERE ... AND item_id IN(SELECT item_id 来自item_tags WHERE tag_id IN(1,2,3))

(这个确切的查询不起作用 - 它是标签上的OR,但这就是我想要的。)

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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