Seleccionar declaración para encontrar duplicados en ciertos campos

415

¿Me pueden ayudar con las declaraciones SQL para encontrar duplicados en múltiples campos?

Por ejemplo, en pseudocódigo:

select count(field1,field2,field3) 
from table 
where the combination of field1, field2, field3 occurs multiple times

y de la declaración anterior, si hay múltiples ocurrencias, me gustaría seleccionar todos los registros, excepto el primero .

JOE SKEET
fuente
3
su pseudocódigo es ambiguo, además no define el orden según el cual no desea el primero. Le sugiero que proporcione algunos datos de muestra.
razón

Respuestas:

840

Para obtener la lista de campos para los que hay varios registros, puede usar ...

select field1,field2,field3, count(*)
  from table_name
  group by field1,field2,field3
  having count(*) > 1

Consulte este enlace para obtener más información sobre cómo eliminar las filas.

http://support.microsoft.com/kb/139444

Editar: como los otros usuarios mencionaron, debe haber un criterio para decidir cómo definir "primeras filas" antes de usar el enfoque en el enlace de arriba. En base a eso, deberá usar un orden por cláusula y una subconsulta si es necesario. Si puede publicar algunos datos de muestra, sería realmente útil.

Rajesh Chamarthi
fuente
42

Menciona "el primero", por lo que supongo que tiene algún tipo de pedido en sus datos. Supongamos que sus datos están ordenados por algún campo ID.

Este SQL debería obtener las entradas duplicadas, excepto la primera. Básicamente, selecciona todas las filas para las cuales existe otra fila con (a) los mismos campos y (b) existe una ID más baja. El rendimiento no será excelente, pero podría resolver su problema.

SELECT A.ID, A.field1, A.field2, A.field3
  FROM myTable A
 WHERE EXISTS (SELECT B.ID
                 FROM myTable B
                WHERE B.field1 = A.field1
                  AND B.field2 = A.field2
                  AND B.field3 = A.field3
                  AND B.ID < A.ID)
Heinzi
fuente
17

Esta es una solución divertida con SQL Server 2005 que me gusta. Asumiré que por "para cada registro excepto el primero", quiere decir que hay otra columna "id" que podemos usar para identificar qué fila es "primera".

SELECT id
    , field1
    , field2
    , field3
FROM
(
    SELECT id
        , field1
        , field2
        , field3
        , RANK() OVER (PARTITION BY field1, field2, field3 ORDER BY id ASC) AS [rank]
    FROM table_name
) a
WHERE [rank] > 1
Nick Vaccaro
fuente
Acabo de notar la etiqueta de SQL Server 2008. Me alegra que mi sugerencia siga siendo válida.
Nick Vaccaro
1
Excelente solución porque también devuelve las filas que deberán eliminarse de la tabla en cuestión
Realto619
1
ayuda a pensar en la lista de campos
PARTICIÓN
6

Para ver valores duplicados:

with MYCTE  as (
    select row_number() over ( partition by name  order by name) rown, *
    from tmptest  
    ) 
select * from MYCTE where rown <=1
manoj Verma
fuente
3

Si está utilizando SQL Server 2005 o posterior (y las etiquetas de su pregunta indican SQL Server 2008), puede usar las funciones de clasificación para devolver los registros duplicados después del primero si el uso de combinaciones es menos deseable o poco práctico por alguna razón. El siguiente ejemplo muestra esto en acción, donde también funciona con valores nulos en las columnas examinadas.

create table Table1 (
 Field1 int,
 Field2 int,
 Field3 int,
 Field4 int 
)

insert  Table1 
values    (1,1,1,1)
        , (1,1,1,2)
        , (1,1,1,3)
        , (2,2,2,1)
        , (3,3,3,1)
        , (3,3,3,2)
        , (null, null, 2, 1)
        , (null, null, 2, 3)

select    *
from     (select      Field1
                    , Field2
                    , Field3
                    , Field4
                    , row_number() over (partition by   Field1
                                                      , Field2
                                                      , Field3
                                         order by       Field4) as occurrence
          from      Table1) x
where     occurrence > 1

Observe después de ejecutar este ejemplo que se excluye el primer registro de cada "grupo" y que los registros con valores nulos se manejan correctamente.

Si no tiene una columna disponible para ordenar los registros dentro de un grupo, puede usar las columnas de partición por columnas.

Bradford Hoagland
fuente
1
CREATE TABLE #tmp
(
    sizeId Varchar(MAX)
)

INSERT  #tmp 
    VALUES ('44'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46'),
        ('44,45,46')


SELECT * FROM #tmp
DECLARE @SqlStr VARCHAR(MAX)

SELECT @SqlStr = STUFF((SELECT ',' + sizeId
              FROM #tmp
              ORDER BY sizeId
              FOR XML PATH('')), 1, 1, '') 


SELECT TOP 1 * FROM (
select items, count(*)AS Occurrence
  FROM dbo.Split(@SqlStr,',')
  group by items
  having count(*) > 1
  )K
  ORDER BY K.Occurrence DESC    
Sr. X
fuente
0

intente esta consulta para tener un conteo de cada instrucción SELECT:

select field1,count(field1) as field1Count,field2,count(field2) as field2Counts,field3, count(field3) as field3Counts
from table_name
group by field1,field2,field3
having count(*) > 1
daryosh setorg
fuente