Udtræk kun den første fra den postenhed, hvor værdien af den angivne kolonne er duplikeret

Side opdateret :
Dato for oprettelse af side :

Normalt, når man kun udtrækker én duplikatpost, er det første, der kommer til at tænke på, at distinct jeg tænker: distinct Giver dig ikke mulighed for at angive en dubletkolonne og en anden kolonne, som du vil hente på samme tid. Derudover opfylder ikke dette krav,distinct fordi det inkluderer ikke-duplikerede poster i udtrækningen.

Jeg tror ikke, du kan forstå, hvad du vil gøre med titlen alene, så lad os bruge en eksempelpost som eksempel. Det, jeg vil gøre, er følgende ekstraktionsresultat.

ID-navn
1 Navn 1
2 Navn 2
3 Navn 3
3 Navn 3@example.com
4 Navn 4 Navn 4@example.com
4 Navn 4@example.com
4 Navn 4@example.com

Få det som følger:

ID-navn
3 Navn 3@example.com
4 Navn 4@example.com

ID 1 og 2 er ikke inkluderet, fordi de ikke er dubletter. ID 3 og 4 er dubletter, så en af dem hentes. Denne gang får vi dog ikke den første post i DB-lagerrækkefølgen. Antag desuden, at du vil have den første linje i navnet i prioriteret rækkefølge under de betingelser, at "Navn indeholder et @-mærke" og "Navn har et lille antal tegn".

Ovenstående betingelse kan opnås med følgende SQL. Vi bruger dog underforespørgsler og har ikke kontrolleret ydeevnen.

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)
)

Dubletrækker kontrolleres having med og count . group by Nøglekolonnen skal kontrolleres udefra, her ID er where kolonnen indsnævret med .

Rangfølgen for hentning af den første række er order by angivet med . charindex Her og len kontroller, om den indeholder det angivne tegn og længden af strengen. top Alt du skal gøre er at få den første række af hver dubletpost ind i .

Oprindeligt er dette fint, men hvis der er to eller flere poster med nøjagtig samme værdi, såsom "ID: 4, Name: Name 4@example.com", vil du uundgåeligt få to poster. row_number Derfor tilføjes den, så den kan identificeres for hver række med , så der kun kan hentes én post med nøjagtig samme værdi. Hvis det er kendt, at nøjagtig den samme post ikke eksisterer, tror jeg row_number , det ville være bedre at kontrollere værdierne af de eksisterende poster uden at tilføje .

Hvis der er flere nøgler, der skal kontrolleres for dubletter, kan du øge antallet af nøglekolonner for hver. Overvej f.eks. følgende post: De kolonner, der skal kontrolleres for dubletter, er "ID1" og "ID2".

ID1 ID2 Navn
1 1 Navn 1
2 1 Navn 2
3 1 Navn 31
3 2 Navn 32
4 1 Navn41
4 2 Navn42
4 2 Navn 4@example.com
5 1 Navn 555@example.com
5 1 Navn 55@example.com
5 2 Navn 5@example.com
6 1 Navn 6
6 1 Navn 66@example.com
6 2 Navn 6
6 2 Navn 6

Resultatet af opkøbet er som følger.

ID1 ID2 Navn
4 2 Navn 4@example.com
5 1 Navn 55@example.com
6 1 Navn 66@example.com
6 2 Navn 6

SQL ser sådan ud: Du kan blot øge den del, hvor nøglekolonnen blev angivet.

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)
)