[英]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.