SQL 查找具有共同成员的集合(关系除法)
Posted
技术标签:
【中文标题】SQL 查找具有共同成员的集合(关系除法)【英文标题】:SQL find sets with common members (relational division) 【发布时间】:2013-05-01 07:46:50 【问题描述】:我有一组单独的“类”和“组”,每组都分配了一个或多个标签。我想为每个组找到包含每个组相同(或更多)标签的类子集。
一些样本数据:
declare @Groups table
(
GroupID int,
TagID int
)
insert @Groups
values (1,1),(1,2),(1,3),
(2,1),(2,2),
(3,1),(3,2),(3,3),(3,4)
declare @Classes table
(
ClassID int,
TagID int
)
insert @Classes
values (1,1),(1,2),
(2,1),(2,2),
(3,1),(3,2),(3,3)
select * from @Groups
select * from @Classes
然后输出:
GroupID TagID
1 1
1 2
1 3
2 1
2 2
3 1
3 2
3 3
3 4
ClassID TagID
1 1
1 2
2 1
2 2
3 1
3 2
3 3
示例结果集如下所示:
declare @Results table
(
GroupID int,
ClassID int
)
insert @Results
values (1,3),(2,1),(2,2),(2,3),(3,null)
select * from @Results
结果输出:
GroupID ClassID
1 3
2 1
2 2
2 3
3 NULL
我了解这是一个关系除法类型的问题,涉及having
和count
。这些帖子描述了我想做什么,但我不知道如何将这些示例应用于上述特定情况:
【问题讨论】:
【参考方案1】:我认为这也应该有效
select distinct g.GroupID, c.ClassID
from @Groups g
left join @Classes c on g.TagID = c.TagID
where not exists (
select *
from @Groups g2
where g2.GroupID = g.GroupID
and g2.TagID not in (
select TagID
from @Classes c2
where c2.ClassID = c.ClassID
)
) or c.ClassID is null
【讨论】:
欢迎来到 SO!和 +1 以获得正确的双重否定方法。我会尽量在生产环境中避免这种情况,因为除非您熟悉它,否则它可能会非常令人费解。 谢谢,标记为为空组正确返回 null 的答案。【参考方案2】:您可以将表格连接在一起,并要求在类中找到该组中的所有标签:
select g.GroupID
, c.ClassID
from @Groups g
join @Classes c
on c.TagID = g.TagID
group by
g.GroupID
, c.ClassID
having count(c.TagID) =
(
select count(*)
from @Groups g2
where g2.GroupID = g.GroupID
)
这不会列出没有匹配类的组,我想不出一个简单的方法。
Example at SQL Fiddle.
【讨论】:
谢谢!这看起来可以完成工作,现在远离测试系统,但一旦完全测试就会确认。 “要求在类中找到组中的所有标签”......也感谢清晰的逻辑,子查询对我来说是缺失的链接。以上是关于SQL 查找具有共同成员的集合(关系除法)的主要内容,如果未能解决你的问题,请参考以下文章