【问题标题】:Select all rows that have at least a list of features with wildcard support选择至少具有支持通配符的功能列表的所有行
【发布时间】:2018-06-02 20:19:57
【问题描述】:

给定一个表定义:

Objects:
 obj_id | obj_name
 -------|--------------
  1     | object1
  2     | object2
  3     | object3

Tags:
  tag_id | tag_name
  -------|--------------
   1     | code:python
   2     | code:cpp
   3     | color:green
   4     | colorful
   5     | image

objects_tags:
  obj_id | tag_id
  -------|---------
   1     | 1
   1     | 2
   2     | 1
   2     | 3
   3     | 1
   3     | 2
   3     | 3

我想从给定列表使用通配符中选择包含所有标签的对象。类似的问题已经被问过好几次了,对简单变体的回答或多或少是这样的:

SELECT obj_id,count(*) c FROM objects_tags
INNER JOIN objects USING(obj_id)    
INNER JOIN tags USING(tag_id)
WHERE (name GLOB 'code*' OR name GLOB 'color*')
GROUP BY obj_id
HAVING (c==2)

但是,此解决方案不适用于通配符。是否可以创建类似的查询来返回每个给定通配符查询返回至少 1 个标签的对象?检查 c>=2 是否不起作用,因为一个通配符标签可以返回多个结果,而另一个可能返回 0 仍然通过查询,即使它不应该。

我考虑构建由客户端软件构建的动态查询,该查询将由 N 个 INTERSECTs(每个标签一个)组成,因为它们可能不会很多,但听起来确实很脏,如果还有更多 SQL 方式那我宁愿用它。

【问题讨论】:

    标签: sql sqlite select tags entity-relationship


    【解决方案1】:

    SQLite 支持WITH clause,所以我会尝试先用它来确定所有标签,然后使用这些标签通过以下方式查找对象。

    示例 (demo) 是为 PostGreSQL 制作的,因为我无法在任何在线测试仪上运行 SQLIte,但我相信您会轻松地将其转换为 SQLite:


    此查询检索所有标签:

    WITH tagss AS (
      SELECT * FROM Tags
      WHERE tag_name LIKE 'code:%' OR tag_name LIKE 'color:%'
    )
    SELECT * FROM tagss;
    
    | tag_id |    tag_name |
    |--------|-------------|
    |      1 | code:python |
    |      2 |    code:cpp |
    |      3 | color:green |
    

    而最终的查询就是这样使用上面的子查询的:

    WITH tagss AS (
      SELECT * FROM Tags
      WHERE tag_name LIKE 'code:%' OR tag_name LIKE 'color:%'
    )
    SELECT obj_id,count(*) c 
    FROM objects_tags
    INNER JOIN tagss USING(tag_id)
    WHERE tag_name IN ( SELECT tag_name FROM tagss) 
    GROUP BY obj_id
    HAVING count(*) >= (
        SELECT count(*) FROM tagss
    )
    
    | obj_id | c |
    |--------|---|
    |      3 | 3 |
    

    【讨论】:

    • 这几乎是完美的,除了它要求所有标签都存在,所以如果有code:%标签,要被选中的对象必须有所有代码标签。至少一个。
    猜你喜欢
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 2014-02-16
    相关资源
    最近更新 更多