【问题标题】:"Tag" searching/exclusion query design issue“标签”搜索/排除查询设计问题
【发布时间】:2012-04-17 16:16:37
【问题描述】:

背景:我正在做一个自制项目来管理我自己的图像集合,并且一直在尝试实现基于标签的搜索,以便我可以轻松地筛选它们。

现在,我正在使用 RedBean 的标记 API 将标记应用于每个图像的数据库条目,但是我停留在我的实现的特定细节上;目前,为了允许搜索多个标签来优化搜索的标签(搜索“ABC XYZ”时,标记的图像必须有标签“ABC”“XYZ”),

我必须使用服务器端语言而不是 SQL 来处理一些处理,然后运行(可选)第二个查询以验证任何返回的图像都没有明确排除的标签结果。 (搜索“ABC -XYZ”时,标记的图像必须有标签“ABC”和not“XYZ”)。

这里的问题是我当前的方法要求我通过我的服务器端代码运行所有结果,并且使任何对合理分页/结果偏移的尝试都不准确。

我的目标是通过一个查询仅获取包含所请求标签(并且不包含任何排除标签)的 post 表的行,并且仍然能够为我的查询使用 LIMIT/OFFSET 参数以合理地获取分页结果。

表架构如下:

Table "post"
Columns:
  id (PRIMARY KEY for post table)
  (image metadata, not relevant to tag search)

Table "tag"
Columns:
  id (PRIMARY KEY for tag table)
  title (string of varying length - assume varchar(255))

Table "post_tag"
Columns:
  id (PRIMARY KEY for post_tag table)
  post_id (associated with column "post.id")
  tag_id (associated with column "tag.id")

如果可能的话,我还希望能够拥有特定于 post 表列的 WHERE 条件。

我应该为查询结构使用什么?我一直在玩左连接,但无法获得解决此问题所需的确切结构。

【问题讨论】:

    标签: sql photo-tagging


    【解决方案1】:

    基本思路如下:

    LEFT OUTER JOIN 是与您要排除的标签匹配的一组帖子。查询中的最后一个 WHERE 子句确保这些帖子中没有一个与第一个 post 表中的条目匹配。

    INNER JOIN 是与所有标签匹配的帖子集。请注意,第二个必须与您在 IN 子句中提供的唯一标签名称的数量相匹配。

    select p.*
    from post p
    left outer join (
        select pt.post_id    
        from post_tag pt
        inner join tag t on pt.tag_id = t.id
        where t.title in ('UVW', 'XYZ')
    ) notag on p.id = notag.post_id 
    inner join (
        select pt.post_id    
        from post_tag pt
        inner join tag t on pt.tag_id = t.id
        where t.title in ('ABC', 'DEF')
        group by pt.post_id
        having count(distinct t.title) = 2
    ) yestag on p.id = yestag.post_id 
    where notag.post_id is null
    --add additional WHERE filters here as needed
    

    【讨论】:

    • 似乎不适用于 SQLite,没有返回行。我将快速将我的测试平台数据库迁移到 MySQL,看看情况如何。
    • MySQL 中也没有骰子。在测试平台数据库中有两个帖子,一个标记为("abc", "def", "ghi"),另一个标记为("abc", "def", "xyz")。尝试使用排除/左外连接 ("xyz") 和搜索/内连接 ("abc", "def") 进行查询,但也没有结果。我会稍微修改一下结构,看看我能不能找到它生气的地方。
    • 刚刚用“解释”运行了查询,我在第一块得到了这个:“在阅读 const 表后注意到了不可能的地方”。
    • 我发现了问题——内部连接需要yestag on p.id = yestag.post_id,而不是notag.post_id。有了这个,我可以确认它也可以在 sqlite 中工作。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2011-07-14
    • 2012-02-04
    • 2014-04-23
    • 2021-02-06
    • 2013-07-19
    • 1970-01-01
    相关资源
    最近更新 更多