我有一个将图像与标签匹配的Web应用程序,我需要创建一种动态优化标记搜索结果的方法。但是,我找不到一个干净的方法来进行SQL查询,而这正是我需要你帮助的地方。
我的想法是,如果我搜索“干净”和“狗”这样的标签,我会得到包含标签“干净”和“狗”的图像结果。如果我还包含标签“little”,我的结果必须缩小到与三个标签关联的图像。
那么,有一个N对N关系,这是正确的方法吗?
我的自然方法是生成类似这样的代码,但我当然不喜欢它的发展方向:
SELECT images.*
FROM images
INNER JOIN image_tags ON ...
INNER JOIN tags ON ...
WHERE tags.tag = @tag1
AND EXISTS
(
SELECT 1
FROM images
INNER JOIN image_tags ON ...
INNER JOIN tags ON ...
WHERE tag = @tag2
AND EXISTS
(
SELECT 1
FROM images
INNER JOIN image_tags ON ...
INNER JOIN tags ON ...
WHERE tag = @tag3
AND EXISTS (...)
...
)
)
当然,那不是很好。有什么想法吗?
谢谢!
答案 0 :(得分:7)
这样的事情可行(我id
使用SELECT
和GROUP BY
,使用您需要的列。
SELECT images.id
FROM images
INNER JOIN image_tags ON ...
INNER JOIN tags ON ...
WHERE tags.tag IN ( @tag1, @tag2, @tag3 )
GROUP BY images.id
HAVING COUNT(*) = @number_of_tags
如果您的示例中有3个标记,则number_of_tags
必须为3,并且连接将导致每个id
匹配3行。
您可以动态创建该查询,也可以使用10个标记对其进行定义,并使用标记中不会出现的值对其进行初始化。
答案 1 :(得分:0)
我不会使用N-N关系,而是使用文本字段来存储标记。
这可能听起来很脏,因为我们正在失去正常性,但标签通常只用于文本搜索而且磁盘空间很便宜。
然后您可以运行
SELECT * FROM images WHERE tags LIKE '%clean%' AND tags LIKE '%dog%'...
答案 2 :(得分:0)
使用相交可以做到这一点:
SELECT images.*
FROM images
WHERE image_id IN
(
SELECT image_id FROM image_tags WHERE tag_id =
(SELECT tag_id FROM tags WHERE tag = @tag1)
INTERSECT
SELECT image_id FROM image_tags WHERE tag_id =
(SELECT tag_id FROM tags WHERE tag = @tag2)
INTERSECT
....
)
这将根据image_tags中的交叉点(匹配所有)标签选择所有图像。