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

时间:2016-10-26 13:25:54

标签: php mysql sql tags request

我目前正在设计一个文件托管网站。我按标签排序文件,我在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。

我做错了什么?

感谢您的帮助

4 个答案:

答案 0 :(得分:0)

你的语法看起来很奇怪。请尝试以下方法:

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`

答案 1 :(得分:0)

我会推荐这样的东西:

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;

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

答案 2 :(得分:0)

首先,您需要获取搜索文本,并将其用作数组,即不是字符串。按空格分割值" "所以你有一个数组,其中每个元素代表一个标记。

从文件中选择* length_of_tags_array =  (从files_tags.tag = tags.id中的标签内部连接files_tags中选择count(1),其中files_tags.file = files.id和tags.name in(" + putyourtagshere +") )

  • 由于您的代码是字符串,因此请在quitations之间添加每个元素
  • 在这种情况下不要使用,因为它会检索其他标签的子串,例如" C"是" C#"
  • 的子字符串
  • 删除主题标签,因为它不在您存储的代码名称

答案 3 :(得分:0)

谢谢你,知道了。

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