我目前正在设计一个文件托管网站。我按标签排序文件,我在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。
我做错了什么?
感谢您的帮助
答案 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 +") )
答案 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"))