选择至少具有通配符支持的功能列表的所有行

时间:2018-06-02 20:19:57

标签: sql sqlite select tags entity-relationship

给出一个表定义:

class Aside extends Component {
  render() {
    return (
      <Sidebar className={this.props.className}>
        <List>
          <Item>Pintrest 1</Item>
          <Item>Pintrest 2</Item>
          <Item>Pintrest 3</Item>
        </List>
      </Sidebar>
    );
  }
}

我想选择包含来自给定列表的通配符的所有标记的对象。类似的问题已被多次询问,并回答更简单的变体看起来或多或少像这样:

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

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

我考虑过构建由客户端软件构建的动态查询,该客户端软件由N c>=2 s(每个标签一个)组成,因为可能不会有很多,但它听起来像是非常脏的解决方案,如果还有更多SQL方式然后我更喜欢使用它。

1 个答案:

答案 0 :(得分: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 |