具有多个标记的SQL请求文件


SQL request files with multiples tags

我目前正在设计一个网站的文件托管。我排序的标签文件,我有一个问题,建立在SQL搜索请求。如果我一次搜索多个标签,我希望能够获得包含所有这些标签的文件。

下面是我想做的一个例子。如果我的搜索是"#code #python",我的请求必须返回具有这两个标签的文件(在本例中id为2的文件)。如果搜索只是"#code",请求必须返回文件2和文件3。

这是我如何存储所有的数据,我有一个表的文件,一个标签和另一个与文件和标签之间的链接(files_tags)。

Table Tags 
------------------------
| id | name            |
------------------------
|  1 | Code            |
------------------------
|  2 | Python          |
------------------------
|  3 | PHP             |
------------------------
Table Files
------------------------
| id | name            |
------------------------
| 1  | python.pdf      | ( #python )
------------------------
| 2  | main.py         | ( #code #python )
------------------------
| 3  | class.php       | ( #code #php )
------------------------
Table files_tags
------------------------
| id | tag | file      |
------------------------
| 1  |  1  | 2         |
------------------------
| 2  |  1  | 3         |
------------------------
| 3  |  2  | 1         |
------------------------
| 4  |  2  | 2         |
------------------------
| 5  |  3  | 3         |
------------------------

我当前的请求是:

SELECT DISTINCT `files`.* FROM `files`, `files_tags`, `tags` WHERE `files`.`id` = `files_tags`.`file` AND `files_tags`.`tags` = `tags`.`id` AND `tags`.`name` LIKE %"#code #python"%;

但是它得到了所有3个文件,而不仅仅是文件2。

我做错了什么?

Thanks for help

您的语法看起来很奇怪。试试下面这个:

SELECT `files`.`id`, `files`.`name`
FROM `files` 
      JOIN `files_tags` ON `files`.`id`=`files_tags`.`file`
      JOIN `tags` ON `files_tags`.`tag` = `tags`.`id` 
WHERE `tags`.`name` IN ('code','python');
GROUP BY `files`.`id`, `files`.`name`

我建议这样做:

SELECT f.*
FROM `files` f JOIN
     `files_tags` ft
     ON f.id = ft.file JOIN
    `tags` t
     ON ft.tags = t.id
WHERE FIND_IN_STR(t.name, @SearchStr)
GROUP BY f.id
HAVING COUNT(*) = LENGTH(@SearchStr) - LENGTH(REPLACE(@SearchStr, ',', '')) + 1;

可以自由地更改搜索字符串的格式。而不是"#",只是使用逗号(没有空格)。当然,上面的代码可以调整为支持"#",但是代码需要更多的字符串操作。

首先,您应该使用您的搜索文本,并将其用作数组,也就是说,不是字符串。用空格" "分隔值,这样就得到一个数组,每个元素代表一个标签。

select * from files wherelength_of_tags_array =select count(1) from tags inner join files_tags on files_tags。标签=标签。Id,其中files_tags。File = files。Id和tag .name in ("+putyourtagshere+"))

  • 因为你的标签是字符串,所以在引号之间添加每个元素
  • 不要在这种情况下使用,因为它会检索标签的子字符串,而不是其他标签,如"C"是" c# "的子字符串
  • 也删除标签,因为它不在您存储的标签名称中

谢谢你,它的工作知道。

select * from files where 2 = (select count(1) from tags inner join files_tags on files_tags.tag = tags.id where files_tags.file = files.id and tags.name in ("code","python"))