2010-12-13 18 views
391

¿Puede ayudarme con las declaraciones de SQL para encontrar duplicados en múltiples campos?Seleccionar instrucción para encontrar duplicados en ciertos campos

Por ejemplo, en pseudo código:

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

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

+1

su pseudo código es ambiguo, además de que no definen orden según la cual no desea que la primera. sugiero que den algunos datos de muestra. – Unreason

Respuesta

795

para obtener la lista de campos para los cuales existen varios registros, se puede utilizar ..

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

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

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

Edit: Como mencionan los otros usuarios, no debería ser un criterio para decidir cómo se defina "primeras filas" antes de utilizar el enfoque en el enlace anterior. En base a eso, necesitarás usar una cláusula order by y una sub query si es necesario. Si puede publicar algunos datos de muestra, realmente sería útil.

42

Usted menciona "el primero", así que supongo que tiene algún tipo de orden sobre sus datos. Supongamos que sus datos están ordenados por algún campo ID.

Este SQL debe obtener las entradas duplicadas a excepción de la primera. Básicamente selecciona todas las filas para las cuales existe otra fila con (a) los mismos campos y (b) una ID más baja. El rendimiento no será bueno, 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) 
3

Si está utilizando SQL Server 2005 o posterior (y las etiquetas para indicar su pregunta de SQL Server 2008), se puede utilizar la jerarquización funciones para devolver los registros duplicados después de la primera, si el uso de uniones 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 

Aviso 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 utilizar las columnas de partición por columnas de orden por.

17

Esta es una solución divertida con SQL Server 2005 que me gusta. Voy a suponer que por "para cada registro, excepto para 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 
+0

Acabo de notar la etiqueta de SQL Server 2008. Me alegra que mi sugerencia aún sea válida. –

+1

Excelente solución porque también devuelve las filas que deberán eliminarse de la tabla en la pregunta – Realto619

+1

, ayuda a pensar en la lista de campos PARTITION BY como una lista de campos PK – bkwdesign

5

Para ver valor duplicado

with MYCTE as (
       select row_number() over (partition by name order by name) rown, * from tmptest 

       ) 
       select * from MYCTE where rown <=1 
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  
Cuestiones relacionadas