Mysql连接查询多个“标签” (多对多关系)匹配所有标签?

发布于 2024-09-10 09:10:35 字数 1079 浏览 0 评论 0原文

我正在尝试查询与所有给定标签集匹配的对象。

基本上,我希望用户能够添加越来越多的标签来过滤或“缩小”他们的搜索结果,就像 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“隐藏”。

如何匹配所有标签以获得我想要的“缩小范围”或“向下钻取”效果?谢谢。

I am trying to query for Objects that match ALL of a given set of Tags.

Basically I want users to be able to add on more and more Tags to filter or "narrow down" their search results, kind of like newegg.com does.

My table structure is a table of Objects, a table of Tags, and a MANY:MANY relation table ObjectsTags. So I have a JOIN query like so:

SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)

I tried using an IN clause/condition, like this:

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

But I learned that this simulates a series of ORs, so the more tags you add to the query the MORE results you get, instead of the result set narrowing down like I was hoping.

I also tried doing multiple LIKE WHERE conditions, ANDed together:

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

But this returns no results, since when the results are grouped together the OUTER JOINed Tags.name column just contains 'tag1', and not also 'tag2'. The result row where 'tag2' matched is "hidden" by the GROUPing.

How can I match ALL of the tags to get the "narrow down" or "drill down" effect that I am after? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

桃气十足 2024-09-17 09:10:35

使用:

  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。

Use:

  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

You were missing the HAVING clause.

There's no need to LEFT JOIN if you want only rows where both tags exist.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文