Udtræk kun den første fra den postenhed, hvor værdien af den angivne kolonne er duplikeret
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)
)