2017-06-27 17 views
1

我有一个类似下面的表,其中包含一组Groups,它们包含唯一(在其内部)Values。我想知道哪些组是其他组的完整子集。当然,小组不应该被视为自己的子集。在SQL中查找其他组的子集的组

grouptable将:

ID | Group | Value 
================== 
00 | A | 1 
01 | A | 2 
02 | A | 3 
03 | B | 1 
04 | B | 3 
05 | C | 7 
06 | D | 2 

我想要什么(在Smaller组的每个元素包含在Bigger组):

Smaller | Bigger 
================ 
    B  | A 
    D  | A 

我已经尝试了一些不同的查询,但我可以围绕如何要求Bigger组中的每个元素都包含在Samller组中。

我已经能够做的最好的是这个,它应该在另一个组中找到包含任意匹配Value的组。我如何将任何变成全部

-- Groups where G1 ⊆ G2 
SELECT G1.Group, G2.Group 
FROM GroupTable G1 
JOIN GroupTable G2 ON G2.Group <> G1.Group 
WHERE G1.Value = G2.Value 
GROUP BY G1.Group, G2.Group; 

回答

1

低于第一的SQL例如加入[集团]的给别人用相同的[值]的。

与Sergio Prats的回答类似,当加入的[Group]的总唯一值与[Group]总共的唯一值相同时,则将其保持为[更小]。

具有总计的CTE用于在连接中重复使用。

而且top 1 with ties用于只保留最大[更大]

declare @GroupTable table (ID int identity(1,1), [Group] char(1), Value int); 

insert into @GroupTable ([Group], Value) values 
('A',1),('A',2),('A',3),('B',1),('B',3),('C',7),('D',2),('E',3); 

;with CTE as 
(
    select [Group], count(distinct [Value]) as Total 
    from @GroupTable 
    group by [Group] 
) 
select top 1 with ties 
Q1.Group1 as [Smaller], 
Q1.Group2 as [Bigger] 
from 
(
    select 
    t1.[Group] as Group1, 
    t2.[Group] as Group2, 
    count(distinct t1.Value) as Total1 
    from @GroupTable t1 
    join @GroupTable t2 ON (t1.Value = t2.Value AND t1.[Group] != t2.[Group]) 
    group by t1.[Group], t2.[Group] 
) Q1 
join CTE c1 on (Q1.Group1 = c1.[Group] and Q1.Total1 = c1.Total) 
left join CTE c2 on (Q1.Group2 = c2.[Group]) 
order by c2.Total desc, Q1.Group2; 

返回:

Smaller Bigger 
B  A 
D  A 
E  A 
1

假设您没有重复的值(如您的问题指定),那么您非常接近。你基本上需要一个left joinhaving条款:

select gt.group as smaller_group, gr2.group as bigger_group 
from grouptable gt left join 
    grouptable gt2 
    on gt2.value = gt.value and 
     gt2.group <> gt.group 
group by gt.group, gr2.group 
having count(*) = count(gt2.group); 

having子句说,值的一组给定的数量相匹配的第二组中的数量。

1

假设每个集团和值没有重复,你可以试试这个:

SELECT G1.[Group] as smaller, G2.[Group] AS bigger FROM 
(SELECT [Group], count(*) AS Num FROM GroupTable GROUP BY [Group]) G1 
INNER JOIN 
(SELECT A1.[Group], A2.[Group] as SmallGroup, count(*) AS Num2 
    FROM GroupTable A1 INNER JOIN GroupTable A2 ON 
    A1.[Value] = A2.[Value] 
    WHERE A1.[Group] <> A2.[Group] 
    GROUP BY A1.[Group], A2.[Group]) G2 
    ON G1.[Group] = G2.SmallGroup 
    WHERE Num2 = Num 
相关问题