从与另一个表具有相同关系的表中获取字段

时间:2009-03-16 20:04:26

标签: sql mysql join filter tags

我会尽力解释我的情况。 我正在建立一个网站,您可以通过浏览标签找到主题。没什么奇怪的。虽然我对某些查询有些棘手的时间。它们对你来说可能很容易,我的思绪因做大量工作而变得混乱:P。

我有表格“主题”和“标签”。它们使用表tags_topics连接,其中包含topic_id和tag_id。当用户想要查找主题时,他们可能首先选择一个要过滤的标签,然后将另一个添加到过滤器中。然后我查询获取具有两个所选标签的所有主题。它们也可能有其他标签,但它们必须选择要过滤的标签。要过滤的标记数量不同,但我们始终有一个用户选择的标记列表可供过滤。 这主要是在Filtering from join-table中回答的,我选择了多连接解决方​​案。

现在我需要获取用户可以过滤的标记。因此,如果我们已经定义了2个标签的过滤器,我需要获取所有标签,但过滤器中的标签与包含过滤器中所有标签的主题相关联。这可能听起来很奇怪,所以我举一个实际的例子:P

假设我们有三个主题:网球,健身房和高尔夫。

  • 网球有标签:运动,球,球场和球拍
  • gym有标签:运动,训练和肌肉
  • 高尔夫有标签:运动,球,棒和外面

    1. 用户选择标签运动,所以我们显示所有三个网球,健身房和高尔夫球,并且我们展示球,球场,球拍,训练,肌肉,棒和外面作为其他可能的过滤器。
    2. 用户现在将球添加到过滤器。过滤器现在是运动和球,所以我们展示网球和高尔夫的主题,球场,球拍,棒和外面的其他可能的过滤器。
    3. 用户现在将球场添加到过滤器中,因此我们将网球和球拍作为额外的可能过滤器显示。

我希望我有所作为。顺便说一下,我正在使用MySQL。

4 个答案:

答案 0 :(得分:0)

SELECT   topic_id
FROM     topic_tag
WHERE    tag_id = 1
      OR tag_id = 2
      OR tag_id = 3
GROUP BY topic_id
HAVING   COUNT(topic_id) = 3;

上面的查询将获得所有三个tag_id分别为1,2和3的topic_ids。然后将其用作子查询:

SELECT tag_name
FROM   tag
       INNER JOIN topic_tag
ON     tag.tag_id = topic_tag.tag_id
WHERE  topic_id  IN
                     ( SELECT  topic_id
                     FROM     topic_tag
                     WHERE    tag_id = 1
                           OR tag_id = 2
                           OR tag_id = 3
                     GROUP BY topic_id
                     HAVING   COUNT(topic_id) = 3
                     )
   AND
       (
              tag.tag_id <> 1
           OR tag.tag_id <> 2
           OR tag.tag_id <> 3
       )

我认为这就是你要找的东西。

答案 1 :(得分:0)

SELECT DISTINCT `tags`.`tag`
FROM `tags`
LEFT JOIN `tags_topics` ON `tags`.`id` = `tags_topics`.`tag_id`
LEFT JOIN `topics` ON `tags_topics`.`topic_id` = `topics`.`id`
LEFT JOIN `tags_topics` AS `tt1` ON `tt1`.`topic_id` = `topics`.`id`
LEFT JOIN `tags` AS `t1` ON `t1`.`id` = `tt1`.`tag_id`
LEFT JOIN `tags_topics` AS `tt2` ON `tt2`.`topic_id` = `topics`.`id`
LEFT JOIN `tags` AS `t2` ON `t2`.`id` = `tt2`.`tag_id`
LEFT JOIN `tags_topics` AS `tt3` ON `tt3`.`topic_id` = `topics`.`id`
LEFT JOIN `tags` AS `t3` ON `t3`.`id` = `tt3`.`tag_id`
WHERE `t1`.`tag` = 'tag1'
AND `t2`.`tag` = 'tag2'
AND `t3`.`tag` = 'tag3'
AND `tags`.`tag` NOT IN ('tag1', 'tag2', 'tag3')

答案 2 :(得分:0)

Select a.topic_id
  from join_table a
 where exists( select *
                 from join_table b
                where a.tag_id = b.tag_id
                  and b.topic_id = selected_topic )
 group by a.topic_id
 having count(*) = ( select count(*)
                       from join_table c
                      where c.topic_id = selected_topic )

应该为您提供包含selected_topic所有标记的主题列表。

答案 3 :(得分:0)

从头到尾的通用解决方案但容易产生错别字:

  CREATE VIEW shared_tags_count AS
  SELECT topic_to_tag1.topic_id AS topic_id1, topic_to_tag2.topic_id AS topic_id2, COUNT(*) as number
    FROM topic_to_tag as topic_to_tag1
         JOIN topic_to_tag as topic_to_tag2
         ON topic_to_tag1.topic_id <> topic_to_tag2.topic_id
             AND topic_to_tag1.tag_id = topic_to_tag2.tag_id
GROUP BY topic_to_tag1.topic_id, topic_to_tag2.topic_id;

  CREATE VIEW tags_count AS
  SELECT topic_id, COUNT(*) as number
    FROM topic_to_tag
GROUP BY topic_id

CREATE VIEW related_topics AS
SELECT shared_tags_count.topic_id1, shared_tags_count.topic_id2
  FROM shared_tags_count
       JOIN tags_count
         ON topic_id=topic_id1
            AND shared_tags_counts.number = tags_count.number

CREATE VIEW related_tags AS
SELECT related_topics.topic_id1 as topic_id, topic_to_tag.tag_id
  FROM related_topics
       JOIN topic_to_tag
       ON raleted_topics.tag_id2 = topic_to_tag.topic_id

您只需查询related_tags视图。

有趣的挑战顺便说一句。