Извличане само на първата от единицата за запис, където стойността на зададената колона се дублира
Обикновено, когато извличате само един дублиран запис, първото нещо, което ми идва на ум, е 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)
)