I have separate sets of "classes" and "groups", each of which has been assigned one or more tags. I would like to find, for each group, the subset of classes that contains the same (or more) tags for each group.
Some sample data:
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
And output:
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
An example result set would look like this:
declare @Results table
(
GroupID int,
ClassID int
)
insert @Results
values (1,3),(2,1),(2,2),(2,3),(3,null)
select * from @Results
Results output:
GroupID ClassID
1 3
2 1
2 2
2 3
3 NULL
I understand this is a relational division type problem, involving having
and count
. These posts describe what I want to do, but I can't figure out how to apply the examples to the particular case above:
- http://weblogs.sqlteam.com/peterl/archive/2010/07/02/Proper-Relational-Division-With-Sets.aspx
- SQL Join only if all records have a match
- How can I structure a query to give me only the rows that match ALL values in a CSV list of IDs in T-SQL
- SQL: select sets containing exactly given members
- An sql query to find users with common tags in a defined set
I think this should also work
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
You can join the tables together, and demand that all tags from the group are found in the class:
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
)
This does not list groups without a matching class, and I can't think of a simple way to do so.
来源:https://stackoverflow.com/questions/16314527/sql-find-sets-with-common-members-relational-division