Mysql连接查询匹配所有标签的多个“标签”(多对多关系)?
Posted
技术标签:
【中文标题】Mysql连接查询匹配所有标签的多个“标签”(多对多关系)?【英文标题】:Mysql join query for multiple "tags" (many-to-many relationship) that matches ALL tags? 【发布时间】:2011-03-17 02:33:34 【问题描述】:我正在尝试查询与所有给定标签集匹配的对象。
基本上,我希望用户能够添加越来越多的标签来过滤或“缩小”他们的搜索结果,就像 newegg.com 所做的那样。
我的表结构是一个对象表、一个标签表和一个 MANY:MANY 关系表 ObjectsTags。所以我有一个这样的 JOIN 查询:
SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)
我尝试使用 IN 子句/条件,如下所示:
SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)
WHERE Tags.name IN ('tag1','tag2')
GROUP BY Objects.id
但我了解到,这模拟了一系列 OR,因此添加到查询中的标签越多,得到的结果就越多,而不是像我希望的那样缩小结果集。
我还尝试了多个 LIKE WHERE 条件,并一起使用:
SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)
WHERE Tags.name LIKE 'tag1'
AND Tags.name LIKE 'tag2'
GROUP BY Objects.id
但这不会返回任何结果,因为当结果组合在一起时,OUTER JOINed Tags.name 列只包含“tag1”,而不包含“tag2”。 'tag2' 匹配的结果行被 GROUPing “隐藏”。
如何匹配所有标签以获得我所追求的“缩小”或“向下钻取”效果?谢谢。
【问题讨论】:
【参考方案1】:用途:
SELECT *
FROM OBJECTS o
JOIN OBJECTSTAGS ot ON ot.object_id = o.id
JOIN TAGS t ON t.id = ot.tag_id
WHERE t.name IN ('tag1','tag2')
GROUP BY o.id
HAVING COUNT(DISTINCT t.name) = 2
您缺少 HAVING 子句。
如果您只想要两个标签都存在的行,则无需 LEFT JOIN。
【讨论】:
如果您在 OBJECTTAGS 中的这对列上没有主键或唯一约束/索引以确保没有重复项(这些将是误报),则 DISTINCT 是必要的。跨度> 效果很好!谢谢!从未想过以这种方式使用 HAVING 来计算行数。供其他人参考:我正在用 php 构建查询,以便 HAVING 子句与我正在搜索的标签数量相匹配,所以如果它是 ('tag1', 'tag2', 'tag3') 我正在寻找 HAVING COUNT(DISTINCT t.name) = 3,以确保他的结果具有所有标签。 很棒的答案。谢谢! 这个答案救了我的命!非常感谢!以上是关于Mysql连接查询匹配所有标签的多个“标签”(多对多关系)?的主要内容,如果未能解决你的问题,请参考以下文章