Set包含SQL中的其他set

时间:2018-01-14 01:10:08

标签: sql sql-server

是否有人知道如何找到包含所有其他集合的集合

id elem
1    A
1    C
2    B 
2    D
2    A
2    C  
3    A
3    E
3    F
4    F
4    F

我想得到这个:

id
2
3

在这种情况下, id 2 包含(A,C) - 所有 id 1 的设置 并且 id 3 包含(F) - 所有 id 4

的设置

在我的查询中,我需要获取包含所有set(所有元素)的所有id至少一个id 我将非常感激。谢谢。

2 个答案:

答案 0 :(得分:1)

我没有太多关于这个,但它很感兴趣,所以我猜。我使用的是SQL Server

Follow along in Rextester

我提交了嵌套选择的答案,然后我按照一步一步的逻辑来说明发生了什么:

建立快速表格

CREATE TABLE a (id int, t varchar(10))
INSERT INTO a (id, t)
VALUES (1,'A'),(1,'B'),(1,'B'),(1,'B'),(2,'A')
,(2,'B'),(2,'C'),(3,'C'),(3,'D'),(4,'A'),(5,'P');

以下是解决方案:

select distinct p_id supersets from 
(
    select e.p_id, e.c_id, count(*) matches from (
        select distinct c.id p_id, c.t p_t, d.id c_id, d.t c_t from a c
        inner join a d on c.t = d.t and c.id <> d.id) e
    group by e.p_id, e.c_id) sup
inner join
    (select id, count(distinct t) reqs from a group by id) sub
on sub.id = sup.c_id and sup.matches = sub.reqs;

以下是帮助解释我为什么做我正在做的事情的逻辑步骤:

--Step1 
--Create a list of matches between (distinct) values where IDs are not the same
select distinct c.id p_id, c.t p_t, d.id c_id, d.t c_t from a c
inner join a d on c.t = d.t and c.id <> d.id;

--Step2
--Create a unique list of parent IDs and their child IDs and the # of distinct matches
--For example 2 has 2 matches with 1 and vice versa
select e.p_id, e.c_id, count(*) matches from (
        select distinct c.id p_id, c.t p_t, d.id c_id, d.t c_t from a c
        inner join a d on c.t = d.t and c.id <> d.id) e
group by e.p_id, e.c_id;

--Step2a
--Create a sub query to see how many distinct values are in each "Set"
select id, count(distinct t) reqs from a group by id;

现在我们将它们全部放在连接中(上面,第一个),以确保从Parent到Child的匹配总数占子值的100%,即(是超集)

答案 1 :(得分:1)

我认为以下是您想要的:

select t1.id
from t t1 join
     (select t.*, count(*) over (partition by id) as cnt
      from t
     ) t2
     on t1.elem = t2.elem and t1.id <> t2.id
group by t1.id, t2.id, t2.cnt
having count(*) = cnt;

这会根据元素将每个id与彼此的id匹配。如果匹配数等于第二组中的计数,那么所有匹配 - 你有一个超集。

我注意到你有重复的元素。让我们用CTE来处理这个问题:

with t as (
      select distinct id, elem
      from t
     )
select t1.id
from t t1 join
     (select t.*, count(*) over (partition by id) as cnt
      from t
     ) t2
     on t1.elem = t2.elem and t1.id <> t2.id
group by t1.id, t2.id, t2.cnt
having count(*) = cnt;