我目前正在设计一个网站的文件托管。我排序的标签文件,我有一个问题,建立在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"))