MySQL:具有多个AND条件的多对多关系

时间:2018-09-12 07:47:50

标签: mysql many-to-many

在我的MySQL数据库中,我与三个表具有多对多关系:

TABLE项, TABLE关系(仅存储项目和标签的ID), TABLE标签

每个项目可以有多个标签,标签也可以与多个项目相关,例如项目“鞋子”可以具有标签“运动”和“皮革”,而标签“运动”可以与项目“鞋子”和“衬衫”相关。

我现在需要做的是选择所有具有一个或多个标记的所有项目,这些标记由AND条件合并,例如我想找到所有带有标签“ sport”和标签“ leather”相关的商品。

是否可以仅使用一个查询就以AND条件检索请求的数据,还是需要构建子查询(或类似的查询)?

另一种方法是使所有带有这样的标签的标签与OR组合在一起:

SELECT *
FROM item
LEFT JOIN relation
    ON item.id = item_id
    LEFT JOIN tag
    ON tag.id = tag_id
WHERE (tag = 'sport' OR tag = 'leather')
GROUP BY item.id;

然后过滤掉没有所有必需标签的标签,但是我宁愿数据库来完成工作,而不是获取不必要的项目然后进行迭代。

2 个答案:

答案 0 :(得分:1)

您可以稍微更改当前查询以获取所需结果:

SELECT i.id, i.name    -- OK to select name assuming id is the PK
FROM item i
LEFT JOIN relation r
    ON i.id = r.item_id
LEFT JOIN tag t
    ON t.id = r.tag_id
WHERE t.tag IN ('sport', 'leather')
GROUP BY i.id
HAVING COUNT(DISTINCT t.tag) = 2;

这将返回同时具有sportleather标签的所有项目。它通过按项目进行聚合来工作(就像您已经在做的那样),但是然后在HAVING子句中断言有两个不同的匹配标签。由于我们在WHERE子句中仅限制了这两个标签,因此如果HAVING检查在聚合后通过,则表明该项目是匹配项。

答案 1 :(得分:1)

您需要使用HAVING命令, 是的,复杂性将迅速上升到子查询级别...

SELECT item.id,
COUNT(*) AS cnt
FROM item
LEFT JOIN relation
    ON item.id = item_id
    LEFT JOIN tag
    ON tag.id = tag_id
WHERE (tag = 'sport' OR tag = 'leather')
GROUP BY item.id
HAVING
 cnt >= 1

;