1

我会尽力解释我的情况。我正在制作一个网站,您可以在其中通过浏览标签找到主题。那里没有什么奇怪的。不过,我在一些查询方面遇到了棘手的问题。它们对你来说可能很容易,我的大脑因为做了很多工作而变得一团糟:P。

我有表格“主题”和“标签”。它们使用包含 topic_id 和 tag_id 的表 tags_topics 连接。当用户想要找到一个主题时,他们可能首先选择一个标签作为过滤依据,然后将另一个标签添加到过滤器中。然后我进行查询以获取具有两个选定标签的所有主题。他们可能还有其他标签,但他们必须选择这些标签作为过滤依据。要过滤的标签数量不同,但我们总是有一个用户选择的标签列表来过滤。这主要在从连接表过滤中得到回答,我选择了多个连接解决方​​案。

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

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

  • 网球有标签:运动、球、球场和球拍
  • 健身房有标签:运动,训练和肌肉
  • 高尔夫有标签:运动、球、棒和户外

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

我希望我有点道理。顺便说一句,我正在使用 MySQL。

4

4 回答 4

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_id。然后将其用作子查询:

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
       )

我想这就是你要找的。

于 2009-03-16T20:22:59.587 回答
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')
于 2009-03-16T20:23:36.823 回答
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 的所有标签。

于 2009-03-16T20:32:02.840 回答
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 视图。

顺便说一句,有趣的挑战。

于 2009-03-16T20:33:13.837 回答