简体   繁体   English

Mysql JOIN用于项目和标签

[英]Mysql JOIN for items and tags

Consider three tables: one of items, one of tags on those items, and the third which maps tag ids to tag names. 考虑三个表:一个是项目,一个是这些项目上的标签,第三个是将标签ID映射到标签名称。

Items: 项目:

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

Tags: 标签:

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

Tag Names: 标签名称:

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

So only item 1 has tags TAG_A, TAG_B and TAG_C. 因此,只有第1项具有标签TAG_A,TAG_B和TAG_C。

How do you do a select that retrieves all items which have TAG_A, TAG_B and TAG_C without doing 3 INNER JOINs? 你怎么做一个选择,检索所有有TAG_A,TAG_B和TAG_C的项目而不做3个内部联接? In other words, I know I can do a select and say 换句话说,我知道我可以做一个选择并说出来

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 

but that's got to be inefficient, right? 但那效率低下,对吧?

What about a subquery, like 那个子查询怎么样呢

SELECT * FROM items WHERE ... AND item_id IN (SELECT item_id FROM item_tags WHERE tag_id IN ( 1, 2, 3 )) SELECT * FROM items WHERE ... AND item_id IN(SELECT item_id FROM item_tags WHERE tag_id IN(1,2,3))

(This exact query wouldn't work - it's an OR on tags, but this is what I'm going for. ) (这个确切的查询不起作用 - 它是标签上的OR,但这就是我想要的。)

Try this query - 试试这个查询 -

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)

The first query (aliased sqlvars) creates a single @NumTags variable of how many tags are in the tag name table so it doesn't need to do it on every qualifying tags group by. 第一个查询(别名sqlvars)创建一个@NumTags变量,表示标记名称表中有多少个标记,因此不需要在每个限定标记组中执行此操作。

The second query (aliased HasAllTags) gets items, grouped by itemid having the total count equal to that of the @NumTags. 第二个查询(别名HasAllTags)获取项目,按itemid分组,总计数等于@NumTags的总计数。

Finally, the HasAllTags is joined to items to pull the data. 最后,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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM