我有一个GroupsTable
表,可以通过MWE描述如下。
GroupID MemberID
1 42
2 42
2 43
3 42
3 43
3 44
然后给我另一个表MemberTable
,其中包含一些带有MemberID
的行。例如:
MemberID
42
43
我需要的查询是从第二个表中找到恰好具有GroupID
的匹配MemberID
的查询。我相信以下代码可以正常工作,但是速度非常慢,所以有没有更好的方法来找到答案?
select c.GroupID from (
select g.GroupID
from GroupTable g
join MemberTable m on m.MemberID = g.MemberID
group by g.GroupID
having count(*) = (select count(*) from MemberTable)
) c
left join GroupTable x on x.GroupID = c.GroupID
and x.MemberID not in (select MemberID from MemberTable)
where x.GroupID is null
样本数据:
create table MemberTable (
MemberID int
)
insert into MemberTable
values
(42),
(43);
create table GroupTable (
GroupID int,
MemberID int
);
insert into GroupTable
values
(1, 42), -- only one member
(2, 42), -- both members
(2, 43),
(3, 42), -- one member too many
(3, 43),
(3, 44),
(4, 40), -- two irrelevant members
(4, 41);
这里有一个小提琴:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=ad818a306600286433634fa83c3628a0
答案 0 :(得分:1)
您可以结合使用左联接,分组依据,拥有和计数,如下所示:
DECLARE @Count int;
SELECT @Count = COUNT(*) FROM MemberTable;
SELECT GroupID
FROM GroupTable As G
LEFT JOIN MemberTable As M
ON G.MemberID = M.MemberID
GROUP BY GroupID
HAVING COUNT(DISTINCT G.MemberID) = @Count
AND COUNT(DISTINCT M.MemberID) = @Count
左联接确保您将获取每个组ID的所有记录。
不同的组成员ID数目确保您将仅获得没有成员ID不在成员表中的组ID。
members表的不同计数确保您不会获得恰好具有与members表相同数量的id的组。
更新
在我自己的环境中使用临时表进行测试之后,我证实了自己的怀疑,即性能杀手是count(distinct)。我已更改查询以摆脱它,现在它的速度似乎几乎是问题中查询的两倍:
DECLARE @Count int;
SELECT @Count = COUNT(*) FROM MemberTable;
SELECT GroupID
FROM
(
SELECT DISTINCT GroupID, MemberID
FROM GroupTable
) As G
LEFT JOIN
(
SELECT DISTINCT MemberID
FROM MemberTable
) As M
ON G.MemberID = M.MemberID
GROUP BY GroupID
HAVING COUNT(G.MemberID) = @Count
AND COUNT(M.MemberID) = @Count;
请注意,如果已知MemberTable
始终具有不同的MemberID值,则可以摆脱第二个派生表,而只需将第一个派生表直接连接到MemberTable
。