【问题标题】:How to query for all groups containing one required element and at least one optional element in sqlite3如何在sqlite3中查询包含一个必需元素和至少一个可选元素的所有组
【发布时间】:2021-09-06 22:12:15
【问题描述】:

问题和预期结果

假设我有下表t:

id          f_id        col1
----------  ----------  ----------
1           1           B
2           1           C
3           2           A
4           2           C
5           2           D
6           2           E
7           3           A
8           3           D
9           3           E
10          4           A
11          4           B
12          5           C
13          5           D

我想选择所有不同的 f_id 以使 col1 包含以下值组合之一:

  • A 和 C
  • A 和 D
  • A 和 C 和 D

因此,预期的结果是:

f_id
----------
2
3

自己尝试

基于previous question 我尝试了以下查询

SELECT f_id
FROM t
WHERE (col1 IN ('A', 'C')) or (col1 in ('A', 'D'))
GROUP BY f_id
HAVING COUNT(distinct col1) >= 2;

但是,此查询也与包含 C 和 D 但不包含 A 的组匹配。我不想要这个,因为 A 很重要。上面的查询结果如下:

f_id
----------
2
3
5

如何获得想要的结果?

原始脚本

为了方便,这里是生成原表的代码:

drop table if exists t;
CREATE TABLE t (id INTEGER, f_id INTEGER, col1 VARCHAR(1));
INSERT INTO t (id, f_id, col1) VALUES
  (1, 1, 'B'),
  (2, 1, 'C'),
  (3, 2, 'A'),
  (4, 2, 'C'),
  (5, 2, 'D'),
  (6, 2, 'E'),
  (7, 3, 'A'),
  (8, 3, 'D'),
  (9, 3, 'E'),
  (10, 4, 'A'),
  (11, 4, 'B'),
  (12, 5, 'C'),
  (13, 5, 'D')
;

【问题讨论】:

    标签: database sqlite


    【解决方案1】:

    首先过滤表的行,以便只返回col1中包含'A''C''D'的行和group by f_id
    最后在HAVING子句中设置条件,这样你就只能得到至少包含1个'A'和其他2个的f_ids:

    SELECT f_id
    FROM t
    WHERE col1 IN ('A', 'C', 'D')
    GROUP BY f_id
    HAVING SUM(col1 = 'A') > 0
       AND COUNT(DISTINCT col1) > 1
    

    如果每个f_idcol1 中没有重复项,您可以将COUNT(DISTINCT col1) > 1 更改为COUNT(*) > 1

    或者,EXISTS:

    SELECT t1.f_id
    FROM t t1
    WHERE t1.col1 = 'A'
      AND EXISTS (
        SELECT 1
        FROM t t2
        WHERE t2.f_id = t1.f_id AND t2.col1 IN ('C', 'D')
      )
    

    请参阅demo

    【讨论】:

      【解决方案2】:

      假设组合的顺序并不重要:

      select f_id, group_concat(col1, '') agg
      from t
      GROUP BY f_id
      HAVING (agg LIKE '%A%' AND agg LIKE '%C%')
          OR (agg LIKE '%A%' AND agg LIKE '%D%');
      

      可能有更好的比较方法(例如使用正则表达式)。

      【讨论】:

      • agg 关键字有什么作用?另外,有没有办法让我不必列出所有排列?
      • agg 只是一个别名。我删除了最后一个条件,因为它是多余的。
      猜你喜欢
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      • 2022-01-21
      • 2018-04-19
      • 1970-01-01
      相关资源
      最近更新 更多