Extraiga solo la primera de la unidad de registro en la que se duplica el valor de la columna especificada
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)
)