SQL n对n匹配多个值

时间:2010-01-04 16:29:58

标签: sql

我有一个将图像与标签匹配的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 (...)
    ...
  )
)

当然,那不是很好。有什么想法吗?

谢谢!

3 个答案:

答案 0 :(得分:7)

这样的事情可行(我id使用SELECTGROUP 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中的交叉点(匹配所有)标签选择所有图像。