我有三个表,它们之间有许多关系。 mediarelationstags

      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 1tag 3tag 4

因为:tag 1正在标记Media 1,所以它应返回其所有标签(tag 1tag 3tag 4



例子2

给出:tag 3

返回:返回tag 1tag 2tag 3tag 4

因为:tag 3同时标记了Media 1Media 2,所以返回了它们的所有标记(tag 1tag 2tag 3tag 4



例子3

给定:tag 2tag 3

返回:tag 2tag 3

因为:tag 3标记Media 1Media 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/

10-15 13:58