Extreu només el primer de la unitat de registre on es duplica el valor de la columna especificada
Normalment, quan s'extreu només un registre duplicat, el primer que em ve al cap és distinct
que penso:
distinct
no us permet especificar una columna duplicada i una altra columna que vulgueu recuperar alhora.
A més,distinct
no coincideix amb aquest requisit perquè inclou registres no duplicats en l'extracció.
No crec que pugueu entendre què voleu fer només amb el títol, així que utilitzem un registre de mostra com a exemple. El que vull fer és el següent resultat d'extracció.
Nom | de l'identificador |
---|---|
1 | Nom 1 |
2 | Nom 2 |
3 | Nom 3 |
3 | Nom 3@example.com |
4 | Nom 4 Nom 4@example.com |
4 | Nom 4@example.com |
4 | Nom 4@example.com |
Obten-ho de la següent manera:
Nom | de l'identificador |
---|---|
3 | Nom 3@example.com |
4 | Nom 4@example.com |
Els identificadors 1 i 2 no s'inclouen perquè no són duplicats. Els identificadors 3 i 4 són duplicats, de manera que es recupera un d'ells. Tanmateix, aquesta vegada, no obtindrem el primer registre de l'ordre d'emmagatzematge de la base de dades. A més, suposem que voleu que la primera línia del nom estigui per ordre de prioritat sota les condicions que "El nom conté una marca @" i "El nom té un nombre reduït de caràcters".
La condició anterior es pot obtenir amb el següent SQL. No obstant això, estem utilitzant subconsultes i no hem comprovat el rendiment.
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)
)
Les files duplicades es comproven having
amb i count
. group by
La columna clau que s'ha de comprovar des de fora, aquí ID
la columna es where
redueix per .
L'ordre de precedència per recuperar la primera fila s'especifica order by
per . charindex
Aquí i comproveu len
si conté el caràcter especificat i la longitud de la cadena.
top
Tot el que heu de fer és obtenir la primera fila de cada registre duplicat al .
Originalment, això està bé, però si hi ha dos o més registres amb exactament el mateix valor, com ara "ID: 4, Nom: Nom 4@example.com", inevitablement obtindreu dos registres.
row_number
Per tant, s'afegeix de manera que es pugui identificar per a cada fila amb , de manera que només es pugui recuperar un registre amb exactament el mateix valor.
Si se sap que no existeix exactament el mateix registre, crec row_number
que seria millor comprovar els valors dels registres existents sense afegir .
Si hi ha diverses claus que s'han de comprovar per detectar duplicats, podeu augmentar el nombre de columnes clau per a cadascuna. Per exemple, considereu el registre següent: Les columnes que s'han de comprovar per detectar duplicats són "ID1" i "ID2".
Nom | ID1 | ID2 |
---|---|---|
1 | 1 | Nom 1 |
2 | 1 | Nom 2 |
3 | 1 | Nom 31 |
3 | 2 | Nom 32 |
4 | 1 | Nom41 |
4 | 2 | Nom42 |
4 | 2 | Nom 4@example.com |
5 | 1 | Nom 555@example.com |
5 | 1 | Nom 55@example.com |
5 | 2 | Nom 5@example.com |
6 | 1 | Nom 6 |
6 | 1 | Nom 66@example.com |
6 | 2 | Nom 6 |
6 | 2 | Nom 6 |
El resultat de l'adquisició és el següent.
Nom | ID1 | ID2 |
---|---|---|
4 | 2 | Nom 4@example.com |
5 | 1 | Nom 55@example.com |
6 | 1 | Nom 66@example.com |
6 | 2 | Nom 6 |
L'SQL té aquest aspecte: Simplement podeu augmentar la part on s'ha especificat la columna clau.
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)
)