[英]SQL - Efficient way to make sure both entities represented in a set of key Keypairs exist in final dataset
问题:如何有效地获得一组匹配的人的列表(下面的#People表,每行一个人)(下面的#Keys表),还要确保这些集合是唯一的。
背景:我正在处理数据库中的匹配项集(以KeyId,PersonId1,PersonId2的形式)。 我们有一种自动方法,可将人标记为重复项并将其写入匹配表。 人数不多,但我们通常坐着大约10万场比赛记录和20万名球员。 匹配过程还添加了重复记录,形式是将Person 1与2匹配,也将2与1匹配。此外,我们在逻辑上删除人员记录(IsDeleted = 1),所以不想返回已经有一个人员的匹配项已删除。
我们有一个管理屏幕,人们可以在其中查看重复项,并标记它们是否不是重复项,或删除其中之一。 存在一个问题,即使删除了该对中的一个人,另一个人仍显示在列表中。 下面的SQL试图确保仅返回作为集合存在的人员。
测试数据设置:
CREATE TABLE #Keys
(
KeyId int PRIMARY KEY,
PersonId1 int,
PersonId2 int
)
CREATE TABLE #People
(
PersonId int PRIMARY KEY,
Name varchar(150),
IsDeleted bit
)
INSERT INTO #People
VALUES (1, 'John',0),
(2, 'Madeline',0),
(3, 'Ralph',1),
(4, 'Sarah',0),
(5, 'Jack',0),
(6, 'Olivia',0),
(7, 'Ethan',0),
(8, 'Sophia',0)
INSERT INTO #Keys
VALUES (1,1,2),
(2,2,3),
(3,1,3),
(4,2,1),
(5,4,8),
(6,3,7),
(7,6,1)
SELECT *
FROM #Keys k
JOIN #People p1
ON k.PersonId1 = p1.PersonId
AND p1.IsDeleted = 0
JOIN #People p2
ON k.PersonId2 = p2.PersonId
AND p2.IsDeleted = 0
返回值:
KeyId PersonId1 PersonId2 PersonId Name IsDeleted PersonId Name IsDeleted
1 1 2 1 John 0 2 Madeline 0
4 2 1 2 Madeline 0 1 John 0
5 4 8 4 Sarah 0 8 Sophia 0
7 6 1 6 Olivia 0 1 John 0
SELECT KeyId, p1.PersonId, p1.Name
INTO #Results
FROM #Keys k
JOIN #People p1
ON k.PersonId1 = p1.PersonId
AND p1.IsDeleted = 0
JOIN #People p2
ON k.PersonId2 = p2.PersonId
AND p2.IsDeleted = 0
INSERT INTO #Results
SELECT KeyId, p2.PersonId, p2.Name
FROM #Keys k
JOIN #People p1
ON k.PersonId1 = p1.PersonId
AND p1.IsDeleted = 0
JOIN #People p2
ON k.PersonId2 = p2.PersonId
AND p2.IsDeleted = 0
SELECT * from #Results
order by KeyId
DROP TABLE #People
DROP TABLE #Keys
DROP TABLE #Results
最终查询返回以下集合:
KeyId PersonId Name
1 2 Madeline
1 1 John
4 2 Madeline
4 1 John
5 8 Sophia
5 4 Sarah
7 6 Olivia
7 1 John
但是,问题在于键1和键4具有相同的人员,只是顺序相反。 我想要返回的集合是:
KeyId PersonId Name
1 2 Madeline
1 1 John
5 4 Sarah
5 8 Sophia
7 1 John
7 6 Olivia
首先我会
PersonId1 int,
PersonId2 int
#Keys上的PK并放下KeyId
快速获得独特的方法
select PersonId1, PersonId2
from keys
where PersonId1 < PersonId2
union
select PersonId2, PersonId1
from keys
where PersonId2 < PersonId1
显然,您需要在删除时添加联接
您还可以对#Keys施加一个约束,使PersonId1 <PersonId2
我认为这也会起作用
select PersonId1, PersonId2 from keys
except
select PersonId2, PersonId1 from keys
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.