【问题标题】:Filtering from join-table从连接表过滤
【发布时间】:2010-10-13 11:52:59
【问题描述】:

我遇到了一些棘手的 SQL 查询问题。

在我的 MySQL 数据库中,有表 topic、tags 和 tags_topics 来加入它们。 我想获取共享相同指定标签的主题。例如,假设我有 3 个 id 为 1、2 和 3 的标签,我想获取与标签 1、2 和 3 相关联的所有主题。主题可以有其他标签,但必须有所有指定的标签。

请帮我想想xD

编辑:在这个问题中使用 GROUP BY 找到了解决方案:Fetching only rows that match all entries in a joined table (SQL) 如果有人有更优雅的解决方案,请发布:)

【问题讨论】:

    标签: sql mysql join filtering


    【解决方案1】:
    SELECT 
        topic_id
    FROM
        tags_topics
    WHERE
        tag_id IN (1,2,3)
    GROUP BY
        topic_id
    HAVING
        COUNT(*) > 2  /* or use COUNT(*) = 3 if you know that there cannot be duplicates in the junction table */
    

    【讨论】:

    • +1 用于避免连接,仅使用交集表。这提供了相关的 topic_id 值,但不提供完整的主题实体。
    【解决方案2】:

    JOIN解决方案:

    SELECT t.*
    FROM topics t
     JOIN tags_topics t1 ON (t.id = t1.topicId AND t1.tagId = 1)
     JOIN tags_topics t2 ON (t.id = t2.topicId AND t2.tagId = 2)
     JOIN tags_topics t3 ON (t.id = t3.topicId AND t3.tagId = 3)
    

    GROUP BY解决方案:

    请注意,您需要在 GROUP BY 子句中列出所有 t.* 列,除非您使用 MySQL 或 SQLite。

    SELECT t.*
    FROM topics t JOIN tags_topics tt 
      ON (t.id = tt.topicId AND tt.tagId IN (1,2,3))
    GROUP BY t.id, ...
    HAVING COUNT(*) = 3;
    

    子查询解决方案:

    SELECT t.*
    FROM topics t
    WHERE t.id = ANY (SELECT topicId FROM tags_topics tt WHERE tt.tagId = 1)
      AND t.id = ANY (SELECT topicId FROM tags_topics tt WHERE tt.tagId = 2)
      AND t.id = ANY (SELECT topicId FROM tags_topics tt WHERE tt.tagId = 3);
    

    修改GROUP BY解决方案:

    通过在子查询中隔离搜索来简化 GROUP BY 子句。

    SELECT t.*
    FROM topics t
    WHERE t.id IN (
      SELECT tt.topicId FROM tags_topics tt 
      WHERE tt.tagId IN (1,2,3))
      GROUP BY tt.id HAVING COUNT(*) = 3
    );
    

    【讨论】:

    • COUNT(*) 应该 > 2,因为主题也可以有其他标签。不过感谢所有建议!编辑它,我会把它设置为正确的答案;)
    • @finpingvin - 声明中不考虑其他标签。只要联结表中没有重复项,COUNT(*) = 3 就是正确的
    • 是的,我假设 tags_topics 在 {topicId, tagId} 上有一个主键。顺便说一句,在阅读@Russ Cam 的解决方案后,我编辑了第四个解决方案以避免子查询内的连接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-24
    • 1970-01-01
    • 2018-04-24
    • 2017-11-24
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    相关资源
    最近更新 更多