【问题标题】:MySQL get unique list of things with multiple tag IDsMySQL获取具有多个标签ID的唯一事物列表
【发布时间】:2015-08-17 16:50:53
【问题描述】:

我有 2 个名为 tagsthings 的表,它们都包含一个 id 和一个 name 列。然后,还有第三张表:thing_tags。其中有这样的数据:

╔═══════╤═════════╗
║ tagid │ thingid ║
╟───────┼─────────╢
║     6 │       1 ║
║     6 │       2 ║
║    12 │       1 ║
║    12 │       2 ║
║    12 │       3 ║
║    15 │       4 ║
║    16 │       4 ║
║    21 │       5 ║
╚═══════╧═════════╝

这两列具有对各自表的id 列的外键引用。

我想要做的是获取具有标签#6 和#12 的唯一事物ID 的列表,因此在这种情况下,结果将是ID 12,但不是3,然后在 things 表中找到具有这些 ID 的元素并检索它们。这是我当前的 SQL 查询:

SELECT th.*
FROM thing_tags t
LEFT JOIN things th ON t.id = th.id
WHERE t.id IN (12,6)
ORDER BY th.name ASC

这不能按我想要的方式工作,因为它还给了我表格中的第三件事,并多次返回正确的结果。我该如何修改这个查询,以便只返回那些绑定到所有指定 tagids 的 things,而不仅仅是一个,最后没有重复的行?

【问题讨论】:

    标签: php mysql sql left-join


    【解决方案1】:

    in(...) 是一个 or 比较,而您需要一个 and。您无法更改 in 的行为,但您可以向查询的其余部分添加额外的逻辑,以使 in 的行为就好像它确实具有 and 语义:

    SELECT field1, COUNT(field2) AS cnt
    FROM yourtable
    WHERE field2 IN (6, 12)
    GROUP BY field1
    HAVING cnt = 2
    

    count() 告诉您存在多少 in 字段,然后您使用 having 子句来强制执行您真正想要的数量。在您的情况下,您只需要 2 个,因此您使用 = 2

    having cnt > 2 在语义上等同于“至少有 2 个”。

    【讨论】:

      【解决方案2】:

      这是我最后的尝试::)

      select things.* from things
      inner join thing_tags a on a.thingid = things.id and a.tag_id = 6
      inner join thing_tags b on b.thingid = things.id and b.tag_id = 12
      

      【讨论】:

      • 我在发布此问题之前尝试了类似的解决方案,但 MySQL 返回了一个错误,指出“此版本的 MySQL 不支持带有子查询的 LIMIT & AND/OR/IN”。 AFAIK 我正在运行最新版本。
      • @DJDavid98 感谢您的回复。我已经用另一个选项更新了我的答案。请让我知道这是否有效
      • 您在两个解决方案中都使用IN 和子查询。我的 MySQL 服务器不允许这样做。
      • 我清理了我的答案,只使用内部连接,如果这可行,请告诉我。
      • 刚查了一下,确实有效,但我还是觉得MarcB的方案更正确。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多