Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从与另一个表具有相同关系的表中获取字段_Sql_Mysql_Join_Filter_Tags - Fatal编程技术网

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

Sql 从与另一个表具有相同关系的表中获取字段,sql,mysql,join,filter,tags,Sql,Mysql,Join,Filter,Tags,我会尽力解释我的案子。 我正在制作一个网站,在那里你可以通过浏览他们的标签找到主题。没什么奇怪的。不过,我在一些问题上遇到了棘手的问题。他们可能对你来说很容易,我做了很多工作,脑子里乱七八糟 我有表格主题和标签。它们使用包含topic_id和tag_id的表tags_topics进行连接。当用户想要查找主题时,他们可能首先选择一个要筛选的标记,然后将另一个标记添加到筛选器中。然后,我进行一个查询,以获取包含两个选定标记的所有主题。它们也可能有其他标记,但必须选择这些标记进行筛选。要过滤的标签数量

我会尽力解释我的案子。 我正在制作一个网站,在那里你可以通过浏览他们的标签找到主题。没什么奇怪的。不过,我在一些问题上遇到了棘手的问题。他们可能对你来说很容易,我做了很多工作,脑子里乱七八糟

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

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

假设我们有三个主题:网球、体操和高尔夫

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

用户选择tag sport,所以我们会显示所有三个网球、健身房和高尔夫,并显示球、球场、球拍、训练、肌肉、棍棒和其他可能的过滤器。 用户现在将球添加到过滤器中。过滤器现在是运动和球,所以我们展示的主题是网球和高尔夫,以及球场、球拍、棍子和室外可能的过滤器。 用户现在将球场添加到过滤器中,因此我们显示网球和球拍作为附加的可能过滤器。 我希望我说得有道理。顺便说一下,我正在使用MySQL

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;
上面的查询将获得三个标记ID均为1、2和3的所有主题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
       )
我想这就是你要找的

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

应该为您提供一个主题列表,其中包含所选主题的所有标签。

通用解决方案位于我的头顶,但容易出现拼写错误:

  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
您只需查询相关的标签视图


有趣的挑战顺便说一句。

不清楚是什么让标记1、2和3在某种程度上与众不同,而“一堆其他标记”却没有。为什么它们是必需的,而其余的则不是,我们怎么知道这一点?这是我们可以假设的预定义标记列表吗?您可能希望给出一些表结构并更好地解释这个问题。我想我得到了你想要的,但我花了5次时间才明白。我看到了@achinda99 Ye的精确副本,我会努力把我的问题写得更好@比尔·卡温并不是真的,这次正好相反:P我想你们认为这是重复的,因为我解释得很糟糕。我将试着写一个更好的问题@混乱我将在我的问题中描述使用场景。不用in,你可以做一个内部连接,但是你必须重命名某些列,我感觉很懒。谢谢,这看起来是一个简单的解决方案。与执行子查询相比,在性能方面感觉更好。是的,但它仅限于3个标记。但查询可以在应用程序代码中动态生成,主要是因为表名;我喜欢把问题分解成观点。更多的代码,但当您的模式发生更改时,更容易维护。是的,我可以看到:实际上我从未使用过视图,我可能需要看一看。
  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