Extreu només el primer de la unitat de registre on es duplica el valor de la columna especificada

Pàgina actualitzada :
Data de creació de la pàgina :

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