从连接表过滤

时间:2009-03-15 18:43:24

标签: sql mysql join filtering

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

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

帮助我思考plz xD

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

2 个答案:

答案 0 :(得分:4)

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解决方案:

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

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
);

答案 1 :(得分:3)

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 */