sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo eliminar filas duplicadas en SQL Server 2008?

La forma más sencilla es con una CTE (expresión de tabla común). Uso este método cuando tengo datos sin procesar para importar; lo primero que hago para desinfectarlo es asegurarme de que no haya duplicados, que tengo algún tipo de identificador único para cada fila.

Resumen:

WITH numbered AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY [dupe-column-list] ORDER BY [dupe-column-list]) AS _dupe_num FROM [table-name] WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;

La parte "dupe-column-list" es donde enumera todas las columnas involucradas donde desea que los valores sean únicos. El ORDEN POR es donde usted decide, dentro de un conjunto de duplicados, qué fila "gana" y cuál se elimina. (El "DONDE 1=1" es solo un hábito personal).

La razón por la que funciona es porque Sql Server mantiene una referencia interna única para cada fila de origen que se selecciona en el CTE. Entonces, cuando se ejecuta DELETE, sabe la fila exacta que se eliminará, independientemente de lo que coloque en la lista de selección de su CTE. (Si está nervioso, puede cambiar "ELIMINAR" a "SELECCIONAR *", pero dado que tiene filas duplicadas, no ayudará; si pudiera identificar cada fila de manera única, no estaría leyendo esto .)

Ejemplo:

CREATE TABLE ##_dupes (col1 int, col2 int, col3 varchar(50));
INSERT INTO ##_dupes 
    VALUES (1, 1, 'one,one')
        , (2, 2, 'two,two')
        , (3, 3, 'three,three')
        , (1, 1, 'one,one')
        , (1, 2, 'one,two')
        , (3, 3, 'three,three')
        , (1, 1, 'one,one')
        , (1, 2, '1,2');

De las 8 filas, tiene 5 involucradas con problemas duplicados; 3 filas necesitan ser eliminadas. Puedes ver los problemas con esto:

SELECT col1
    , col2
    , col3
    , COUNT(1) AS _total 
    FROM ##_dupes 
    WHERE 1=1 
    GROUP BY col1, col2, col3
    HAVING COUNT(1) > 1
    ORDER BY _total DESC;

Ahora ejecute la siguiente consulta para eliminar los duplicados, dejando 1 fila de cada conjunto de duplicados.

WITH numbered AS (
    SELECT ROW_NUMBER() OVER(PARTITION BY col1, col2, col3 ORDER BY col1, col2, col3) AS _dupe_num FROM ##_dupes WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;

Ahora le quedan 5 filas, ninguna de las cuales está duplicada.