Извличане само на първата от единицата за запис, където стойността на зададената колона се дублира

Страницата се актуализира :
Дата на създаване на страница :

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