Извличане само на първата от единицата за запис, където стойността на зададената колона се дублира
Обикновено, когато извличате само един дублиран запис, първото нещо, което ми идва на ум, е distinct , че си мисля:
distinct не ви позволява да зададете дублираща се колона и друга колона, която искате да извлечете едновременно.
Освен товаdistinct не отговаря на това изискване, тъй като включва недублиращи се записи в извлечението.
Не мисля, че можете да разберете какво искате да направите само със заглавието, така че нека използваме примерен запис като пример. Това, което искам да направя, е следният резултат от извличането.
| Име на самоличността | |
|---|---|
| 1 | Име 1 |
| 2 | Име 2 |
| 3 | Име 3 |
| 3 | Име 3@example.com |
| 4 | Име 4 Име 4@example.com |
| 4 | Име 4@example.com |
| 4 | Име 4@example.com |
Вземете го по следния начин:
| Име на самоличността | |
|---|---|
| 3 | Име 3@example.com |
| 4 | Име 4@example.com |
ИД 1 и 2 не са включени, защото не са дубликати. IDs 3 и 4 са дубликати, така че един от тях се извлича. Този път обаче няма да получим първия запис в реда за съхранение на БД. Освен това да предположим, че искате първият ред от името по ред на приоритет при условията, че "Името съдържа знак @" и "Името има малък брой знаци".
Горното условие може да бъде получено със следния SQL. Ние обаче използваме подзаявки и не сме проверили производителността.
select
*
from
(select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
select
top(1) RowNum
from
(select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableSub
where
tableMain.ID = tableSub.ID
and exists (
select
*
from
SampleTable
where
tableSub.ID = ID
having
count(*) >= 2
)
order by
case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)
Дублиращите се редове се проверяват having с и count . group by Ключовата колона, която трябва да се провери отвън, тук ID колоната е where стеснена с .
Редът на старшинство за извличане на първия ред се order by определя от . charindex Тук и len проверете дали съдържа посочения знак и дължината на низа.
top Всичко, което трябва да направите, е да получите първия ред на всеки дублиран запис в .
Първоначално това е добре, но ако има два или повече записа с абсолютно еднаква стойност, като например "ID: 4, Name: Name 4@example.com", неизбежно ще получите два записа.
row_number Следователно той е добавен, така че да може да бъде идентифициран за всеки ред с , така че да може да бъде извлечен само един запис с абсолютно същата стойност.
Ако е известно, че точно същият запис не съществува, row_number мисля, че би било по-добре да проверите стойностите на съществуващите записи, без да добавяте .
Ако има няколко ключа, които трябва да бъдат проверени за дубликати, можете да увеличите броя на ключовите колони за всеки от тях. Например, помислете за следния запис: Колоните, които трябва да се проверят за дубликати, са "ID1" и "ID2".
| ID1 | ID2 | Име |
|---|---|---|
| 1 | 1 | Име 1 |
| 2 | 1 | Име 2 |
| 3 | 1 | Име 31 |
| 3 | 2 | Име 32 |
| 4 | 1 | Име41 |
| 4 | 2 | Име42 |
| 4 | 2 | Име 4@example.com |
| 5 | 1 | Име 555@example.com |
| 5 | 1 | Име 55@example.com |
| 5 | 2 | Име 5@example.com |
| 6 | 1 | Име 6 |
| 6 | 1 | Име 66@example.com |
| 6 | 2 | Име 6 |
| 6 | 2 | Име 6 |
Резултатът от придобиването е следният.
| ID1 | ID2 | Име |
|---|---|---|
| 4 | 2 | Име 4@example.com |
| 5 | 1 | Име 55@example.com |
| 6 | 1 | Име 66@example.com |
| 6 | 2 | Име 6 |
SQL изглежда така: Можете просто да увеличите частта, в която е посочена ключовата колона.
select
*
from
(select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
select
top(1) RowNum
from
(select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableSub
where
tableMain.ID1 = tableSub.ID1
and tableMain.ID2 = tableSub.ID2
and exists (
select
*
from
SampleTable
where
tableSub.ID1 = ID1
and tableSub.ID2 = ID2
having
count(*) >= 2
)
order by
case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)