我有三个表,它们之间有许多关系。 media
,relations
和tags
Media Table Relations Table Tags Table
| media-id | media-name | | rel-id | media-id | tag-id | | tag-id | tag-name|
------------------------- ------------------------------ --------------------
| 1 | "Media 1" | | 1 | 1 | 1 | | 1 | "tag 1" |
| 2 | "Media 2" | | 2 | 2 | 2 | | 2 | "tag 2" |
| 3 | 1 | 3 | | 3 | "tag 3" |
| 4 | 2 | 3 | | 4 | "tag 4" |
| 5 | 1 | 4 |
我需要一个MySQL查询,当给出一个或多个标签时,它将返回所有其他可能的标签组合。这里有几个例子。
例子1
给出:
tag 1
返回:
tag 1
,tag 3
和tag 4
因为:
tag 1
正在标记Media 1
,所以它应返回其所有标签(tag 1
,tag 3
和tag 4
)例子2
给出:
tag 3
返回:返回
tag 1
,tag 2
,tag 3
和tag 4
因为:
tag 3
同时标记了Media 1
和Media 2
,所以返回了它们的所有标记(tag 1
,tag 2
,tag 3
,tag 4
)例子3
给定:
tag 2
和tag 3
返回:
tag 2
和tag 3
因为:
tag 3
标记Media 1
和Media 2
,但是只有Media 2
具有tag 2
,所以仅返回其标记,而排除Media 1
的标记我已经搜索了一段时间,但是没有找到与弓形答案有关的任何内容。我最接近此查询的地方是此查询:
SELECT `tags`.`tag-name`
FROM `tags`
WHERE `tags`.`tag-id` IN (
SELECT `relations`.`tag-id`
FROM `relations`
WHERE `relations`.`media-id` IN (
SELECT `relations`.`media-id`
FROM `relations`
WHERE `relations`.`tag-id` IN (
SELECT `tags`.`id`
FROM `tags`
WHERE `tags`.`tag-name` IN ('tag 1')
)
)
)
这很好,也许不是最有效,但我可以理解。
唯一的问题是,如果我要在示例3上运行它,它将返回所有标签,而不是从
Media 1
中排除标签。有没有办法我可以更改MySQL查询来执行此操作?
最佳答案
解决该问题的一般方法是在表和聚合之间进行多个联接,如下所示:
select t2.tag_name
from tags t
inner join relations r on r.tag_id = t.tag_id
inner join media m on m.media_id = r.media_id
inner join relations r2 on r2.media_id = m.media_id
inner join tags t2 on t2.tag_id = r2.tag_id
where t.tag_name in ('tag 2', 'tag 3')
group by t2.tag_name
having count(distinct t.tag_id) = 2
这个:
('tag 2', 'tag 3')
是您要查询获取结果的标签的列表。
以及HAVING子句中条件右侧的数字:
count(distinct t.tag_id) = 2
是该列表中的项目数。
请参见demo。
在只有1个查询标签的情况下,代码可以简化为:
select t2.tag_name
from tags t
inner join relations r on r.tag_id = t.tag_id
inner join media m on m.media_id = r.media_id
inner join relations r2 on r2.media_id = m.media_id
inner join tags t2 on t2.tag_id = r2.tag_id
where t.tag_name = 'tag 1'
group by t2.tag_name
关于mysql - 从与MySQL查询的多对多关系中仅获取可用标签,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59547311/