Extraiga solo la primera de la unidad de registro en la que se duplica el valor de la columna especificada

Actualización de la página :
Fecha de creación de la página :

Normalmente, cuando se extrae un solo registro duplicado, lo primero que me viene a la mente es distinct que pienso, distinct No permite especificar una columna duplicada y otra columna que se desee recuperar al mismo tiempo. Además,distinct no cumple con este requisito porque incluye registros no duplicados en la extracción.

No creo que puedas entender lo que quieres hacer solo con el título, así que usemos un registro de muestra como ejemplo. Lo que quiero hacer es el siguiente resultado de extracción.

Nombre de ID
1 Nombre 1
2 Nombre 2
3 Nombre 3
3 Nombre 3@example.com
4 Nombre 4 Nombre 4@example.com
4 Nombre 4@example.com
4 Nombre 4@example.com

Consíguelo de la siguiente manera:

Nombre de ID
3 Nombre 3@example.com
4 Nombre 4@example.com

Los ID 1 y 2 no se incluyen porque no son duplicados. Los identificadores 3 y 4 son duplicados, por lo que se recupera uno de ellos. Sin embargo, esta vez, no obtendremos el primer registro en el orden de almacenamiento de la base de datos. Además, supongamos que desea que la primera línea del nombre esté en orden de prioridad bajo las condiciones "El nombre contiene una marca @" y "El nombre tiene un pequeño número de caracteres".

La condición anterior se puede obtener con el siguiente SQL. Sin embargo, estamos usando subconsultas y no hemos comprobado el rendimiento.

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

Las filas duplicadas se comprueban having con y count . group by La columna clave que se va a comprobar desde el exterior, aquí ID la columna se where reduce por .

El orden de prioridad para recuperar la primera fila se order by especifica mediante . charindex Aquí, y len compruebe si contiene el carácter especificado y la longitud de la cadena. top Todo lo que necesita hacer es obtener la primera fila de cada registro duplicado en .

Originalmente, esto está bien, pero si hay dos o más registros con exactamente el mismo valor, como "ID: 4, Nombre: Nombre 4@example.com", inevitablemente obtendrá dos registros. row_number Por lo tanto, se anexa para que se pueda identificar para cada fila con , de modo que solo se pueda recuperar un registro con exactamente el mismo valor. Si se sabe que no existe exactamente el mismo registro, creo row_number que sería mejor verificar los valores de los registros existentes sin agregar .

Si hay varias claves que se van a comprobar si hay duplicados, puede aumentar el número de columnas de clave para cada una. Por ejemplo, considere el siguiente registro: Las columnas que se van a comprobar en busca de duplicados son "ID1" e "ID2".

ID1 ID2 Nombre
1 1 Nombre 1
2 1 Nombre 2
3 1 Nombre 31
3 2 Nombre 32
4 1 Nombre41
4 2 Nombre42
4 2 Nombre 4@example.com
5 1 Nombre 555@example.com
5 1 Nombre 55@example.com
5 2 Nombre 5@example.com
6 1 Nombre 6
6 1 Nombre 66@example.com
6 2 Nombre 6
6 2 Nombre 6

El resultado de la adquisición es el siguiente.

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

El SQL tiene el siguiente aspecto: Simplemente puede aumentar la parte en la que se especificó la columna de clave.

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