Select 行,当一个值多次出现时

Select rows when a value appears multiple times

我有一个像这样的table:

+------+------+
|  ID  | Cust |
+------+------+
|   1  |  A   |
|   1  |  A   |
|   1  |  B   |
|   1  |  B   |
|   2  |  A   |
|   2  |  A   |
|   2  |  A   |
|   2  |  B   |
|   3  |  A   |
|   3  |  B   |
|   3  |  B   |
+------+------+

我想获得至少两次 A 和两次 B 的 ID。因此在我的示例中,查询应该 return 只有 ID 1,

谢谢!

这是一个选项;第 1 - 13 行代表示例数据。您可能感兴趣的查询从第 14 行开始。

SQL> with test (id, cust) as
  2    (select 1, 'a' from dual union all
  3     select 1, 'a' from dual union all
  4     select 1, 'b' from dual union all
  5     select 1, 'b' from dual union all
  6     select 2, 'a' from dual union all
  7     select 2, 'a' from dual union all
  8     select 2, 'a' from dual union all
  9     select 2, 'b' from dual union all
 10     select 3, 'a' from dual union all
 11     select 3, 'b' from dual union all
 12     select 3, 'b' from dual
 13    )
 14  select id
 15  from (select
 16          id,
 17          sum(case when cust = 'a' then 1 else 0 end) suma,
 18          sum(case when cust = 'b' then 1 else 0 end) sumb
 19        from test
 20        group by id
 21       )
 22  where suma = 2
 23    and sumb = 2;

        ID
----------
         1

SQL>

在MySQL中:

SELECT id
FROM test
GROUP BY id
HAVING GROUP_CONCAT(cust ORDER BY cust SEPARATOR '') LIKE '%aa%bb%'

在 Oracle 中

WITH cte AS ( SELECT id, LISTAGG(cust, '') WITHIN GROUP (ORDER BY cust) custs
              FROM test
              GROUP BY id )
SELECT id
FROM cte
WHERE custs LIKE '%aa%bb%'

您可以对相关客户使用 group by 和 having ('A' , 'B') 并查询两次(我选择使用 with 来避免多次选择并缓存它)

with more_than_2 as 
(
    select Id, Cust, count(*) c
    from tab
    where Cust in ('A', 'B')
    group by Id, Cust
    having count(*) >= 2
)
select *
from tab
where exists ( select 1 from more_than_2 where more_than_2.Id = tab.Id and more_than_2.Cust = 'A')
and exists ( select 1 from more_than_2 where more_than_2.Id = tab.Id and more_than_2.Cust = 'B')

我只使用两个级别的聚合:

select id
from (select id, cust, count(*) as cnt
      from t
      where cust in ('A', 'B')
      group by id, cust
     ) ic
group by id
having count(*) = 2 and  -- both customers are in the result set
       min(cnt) >= 2     -- and there are at least two instances

您想要的是 match_recognize 的完美人选。给你:

select id_ as id from t
match_recognize
(
    order by id, cust
    measures id as id_
    pattern (A {2, } B {2, })
    define  A as cust = 'A',
            B as cust = 'B'
)

输出:

此致, 拉纳加尔