代码之家  ›  专栏  ›  技术社区  ›  Alpha

SQL N到N匹配多个值

sql
  •  6
  • Alpha  · 技术社区  · 15 年前

    我有一个Web应用程序可以将图像与标记匹配,我需要创建一种动态优化标记搜索结果的方法。但是,我找不到一个清晰的方法来进行SQL查询,这正是我需要您帮助的地方。

    我的想法是,如果我搜索标签“干净”和“狗”,我将有图像结果,有两个标签“干净”和“狗”。如果我也包含标签“小”,我的结果将不得不缩小到与三个标签相关联的图像。

    那么,有一个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 回复  |  直到 11 年前
        1
  •  7
  •   Peter Lang    15 年前

    像这样的东西可以用(我用 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,并且联接将导致每个 身份证件 那是匹配的。

    您可以动态地创建该查询,也可以使用10个标记来定义它,并使用标记中不会出现的值初始化它们。

        2
  •  0
  •   Benoît Vidis    15 年前

    我不会使用N-N关系,而是使用文本字段来存储标记。

    这听起来可能很肮脏,因为我们正在失去正常性,但标签通常只用于文本搜索,磁盘空间是便宜的。

    你就可以跑了

    SELECT * FROM images WHERE tags LIKE '%clean%' AND tags LIKE '%dog%'...
    
        3
  •  0
  •   rosscj2533    15 年前

    使用Intersect可以做到:

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

    这将根据图像标记中的交叉(匹配所有)标记选择所有图像。