Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.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
MySQL搜索包含所有标记的项目_Mysql_Tagging - Fatal编程技术网

MySQL搜索包含所有标记的项目

MySQL搜索包含所有标记的项目,mysql,tagging,Mysql,Tagging,我正在为一个在线图书馆搜索引擎工作,但我有点困在这里。在搜索标签时,或搜索(即带有“tag1”或“tag2”的书籍)工作正常,但和搜索给我带来了一些麻烦 我用于此目的的表(及其列)是: books | book_id, other_info tagmap | map_id, book_id, tag_id tags | tag_id, tag_text 由于用户可以启用/禁用一系列其他搜索选项,因此该查询由PHP生成。搜索标记为“tag1”和“tag2”的书籍时,将生成以下查询: SEL

我正在为一个在线图书馆搜索引擎工作,但我有点困在这里。在搜索标签时,或搜索(即带有“tag1”或“tag2”的书籍)工作正常,但和搜索给我带来了一些麻烦

我用于此目的的表(及其列)是:

books  | book_id, other_info
tagmap | map_id, book_id, tag_id
tags   | tag_id, tag_text
由于用户可以启用/禁用一系列其他搜索选项,因此该查询由PHP生成。搜索标记为“tag1”和“tag2”的书籍时,将生成以下查询:

SELECT DISTINCT b.book_id, b.other_info
FROM books b, tagmap tm, tags t
WHERE b.book_id = "NA"
OR ( (t.tag_text IN ("tag1", "tag2"))
      AND tm.tag_id = t.tag_id
      AND b.book_id = tm.book_id )
HAVING COUNT(tm.book_id)=2
WHERE行(不提供任何结果)在那里,这样就可以更容易地将其他参数串到查询中。我知道这可以处理得更好,但现在这不重要了

当执行OR搜索(相同的查询,但没有have COUNT行)时,它将返回数据库中具有这两个标记之一的两本书,但当搜索数据库中具有这两个标记的一本书时,它将不返回任何内容

这个问题怎么了?这不是做这件事的方法吗?我忽略了什么

谢谢

编辑:根据请求,应返回与书籍相关的每个表中的数据:

books table:
book_id     110

tagmap table:
book_id     110    110
tag_id      15     16

tags table:
tag_id      15     16
tag_text    tag1   tag2
解决方案:我所要做的就是包括

GROUP BY b.book_id

在有计数线之前。就这么简单。taz提供的答案也值得研究,特别是当您的目标是优化搜索查询时。

FROM子句中以逗号分隔的表列表的功能类似于内部联接,因此您的查询将选择tagmaps表和tags表中具有相同标记ID的所有行以及其中的行,books表和tagmaps表中具有相同book ID的所有行。HAVING子句要求从具有相同book ID的结果集中返回两行。books表中只能有一行具有任何给定book ID(假定book ID是books表的主键),因此,这一条件从未得到满足

您需要的是一个没有books表的join。您正在寻找在OR子句的结果中出现两次的同一图书ID(我相信),因此您不希望将图书表与这些结果合并,因为这将确保您永远不会在结果中多次出现同一图书ID

编辑:从概念上讲,您实际上是在结合两种不同的东西。您正在寻找同一本书的标记和标记图,并且您还可以从每本书中获取书籍信息。因此,实际上您正在为tagmaps表中相同图书ID的每个实例提取重复的其他_信息数据,然后使用distinct子句将重复的数据减少到一行,因为您只需要图书ID和其他_信息。我会考虑使用两个查询或一个子查询来实现这一点。也许还有其他更好的方法。我得玩弄它才能弄明白

首先,试试看

SELECT DISTINCT tm.book_id, b.other_info
FROM tagmap tm inner join tags t
    on tm.tag_id = t.tag_id
  left join books b
    on tm.book_id = b.book_id
HAVING count(tm.book_id) = 2
将整个内容包装为子查询,以选择所需的其他图书信息:

SELECT book_id, other_info FROM books WHERE book_id IN
(
   ...
)

好的,看起来我为mysql数据库设计了一个复杂的解决方案(对于任何其他数据库都可以)。因此,数据库结构如下所示:

source (id)
tag(id)
tags(source, tag)
包括以下要求:

  • 获取具有任何选定标记或所有选定标记的源
  • 获取不包含排除标记的源
此处查询:

 SELECT source.id 
 FROM source
 -- optional join, if you need to include sources with tags:
 LEFT JOIN tags tags_include ON source.id = tags_include.source
 -- optional join, if you need to exclude sources with tags
 LEFT JOIN tags tags_exclude ON source.id = tags_exclude.source
      -- here list of excluded tags
      and tags_exclude.tag in(1)
 WHERE
    -- optional condition, tags which you need to include
    tags_include.tag IN (2, 3)
    -- optional condition, which will exlcude sources with excluded tags
    and tags_exclude.source is null
 GROUP BY source.id
 -- optional having, in case when you include tags with "AND" strategy
 -- count should be equal to count of selected tags
 -- if you fetch sources with "OR" strategy, ignore this having
 HAVING count(1) >= 2
 ORDER BY source.id DESC
 LIMIT 0, 50;

因此,此查询将获取50个最新的源,这些源具有id为2和3的标记,而没有id为1的标记。

您可以发布应该显示的表中的数据吗?此外,您应该使用内部联接,而不是逗号分隔的表名列表。使用列表语法计算大型笛卡尔积非常容易出错!唯一会显示的是关于这本书的其他信息,我在other_info一栏中总结了这些信息。或者,您是指运行查询所涉及的所有数据吗?我的意思是,您可以发布您试图显示的行中的实际数据,因为这样有助于查看运行此查询时使用的数据。没有必要看到成千上万的其他行,但有几行会有帮助。我试图查看从查询中返回的多行(没有HAVING子句)是否具有相同的book_id,因为HAVING子句意味着需要返回两行,并且具有相同的book id。事实的确如此,我想我理解。但是,在删除“books b”连接、将每个b.book_id替换为tm.book_id并删除最后一个and子句之后,我仍然没有得到结果。但奇怪的是:我尝试了两个不同的标签,它们也属于一个项目,即使我的查询不正确,它也能很好地工作。但是,其他项目/标签仍然不起作用,这是怎么回事?我找到了解决问题的方法(稍后我会将其添加到问题中),但我肯定会研究类似于您建议的查询。我猜有很多条路通往罗马,嗯。非常感谢你的帮助@没问题。对不起,我没时间早点给你回电话。
groupby
也应该适用于您的目的,尽管您可能仍在提取超出需要的数据。关于仍然没有得到结果,我建议您确保使用JOIN子句显式连接表,而不是使用逗号列表并检查您使用的ID字段是否正确。根据您提供的信息&在没有实际测试SQL的情况下,我认为它应该可以工作。你拉取所有具有相同tagID的标记映射和标记,然后拉取所有具有与每个tagID相同bookID的书籍。是的,我已经使用了另一种方法。在(子查询)中,用
book\u id替换了后面或后面的所有内容,其中子查询是使用PHP生成的查询,每个标记都有内部连接,与此处推荐的查询一样:。我想这也是你的目标。
 SELECT source.id 
 FROM source
 -- optional join, if you need to include sources with tags:
 LEFT JOIN tags tags_include ON source.id = tags_include.source
 -- optional join, if you need to exclude sources with tags
 LEFT JOIN tags tags_exclude ON source.id = tags_exclude.source
      -- here list of excluded tags
      and tags_exclude.tag in(1)
 WHERE
    -- optional condition, tags which you need to include
    tags_include.tag IN (2, 3)
    -- optional condition, which will exlcude sources with excluded tags
    and tags_exclude.source is null
 GROUP BY source.id
 -- optional having, in case when you include tags with "AND" strategy
 -- count should be equal to count of selected tags
 -- if you fetch sources with "OR" strategy, ignore this having
 HAVING count(1) >= 2
 ORDER BY source.id DESC
 LIMIT 0, 50;