sql >> Base de Datos >  >> RDS >> Oracle

6 formas de eliminar filas duplicadas que tienen una clave principal en Oracle

Aquí hay algunas opciones para eliminar filas duplicadas de una tabla en Oracle Database cuando esas filas tienen una clave principal o una columna de identificador único.

En tales casos, la clave principal debe ignorarse al comparar filas duplicadas (debido al hecho de que las claves principales contienen valores únicos).

Datos de muestra

Nuestros ejemplos utilizan los siguientes datos:

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
1 Ladrar Smith
2 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
5 Meneo Johnson
6 Meneo Johnson
7 Meneo Johnson

Podemos ver que las dos primeras filas están duplicadas, al igual que las últimas tres filas.

El DogId columna contiene valores únicos (porque es la clave principal de la tabla), pero estamos ignorando esa columna al comparar duplicados. Es posible que a menudo necesite desduplicar tablas que contienen claves principales, por lo que los siguientes ejemplos se pueden usar para hacer precisamente eso.

Opción 1

Esta es nuestra primera opción para deduplicar la tabla anterior:

DELETE FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    MINUS SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
1 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
5 Meneo Johnson

Los duplicados se han eliminado (pero queda una fila de cada duplicado).

Alternativamente, podemos usar el MAX() función en lugar de MIN() función para cambiar qué filas se eliminan.

Opción 2

En este ejemplo (y los siguientes ejemplos) asumiremos que la tabla ha sido restaurada a su estado original (con los duplicados).

Aquí hay otro ejemplo que elimina los duplicados de la tabla y luego selecciona las filas restantes:

DELETE FROM Dogs WHERE DogId IN (
    SELECT d2.DogId 
    FROM Dogs d1, Dogs d2 
    WHERE d1.FirstName = d2.FirstName 
    AND d1.LastName = d2.LastName 
    AND d1.DogId <> d2.DogId 
    AND d1.DogId=( 
        SELECT MAX(DogId) 
        FROM Dogs d3 
        WHERE d3.FirstName = d1.FirstName 
        AND d3.LastName = d1.LastName
    )
);

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
2 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
7 Meneo Johnson

Note que usé el MAX() función en lugar de MIN() que usé en el ejemplo anterior. Podemos ver el efecto que esto tiene en la operación de eliminación de duplicados. Eliminó diferentes filas de la tabla.

Opción 3

Aquí hay una opción que no requiere el uso de MIN() o MAX() :

DELETE FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.DogId > d2.DogId
);

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
1 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
5 Meneo Johnson

Opción 4

Aquí hay otra opción:

DELETE FROM Dogs
WHERE DogId > (
  SELECT MIN(DogId) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
1 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
5 Meneo Johnson

Opción 5

Cada fila en Oracle tiene un rowid pseudocolumna que devuelve la dirección de la fila. El rowid es un identificador único para las filas de la tabla y, por lo general, su valor identifica de forma única una fila en la base de datos (aunque es importante tener en cuenta que las filas de diferentes tablas que se almacenan juntas en el mismo clúster pueden tener el mismo rowid ).

Por lo tanto, podemos usar el rowid en nuestra consulta en lugar del DogId columna:

DELETE FROM Dogs
WHERE EXISTS (
  SELECT 1 FROM Dogs d2 
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
  AND Dogs.rowid > d2.rowid
);

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
1 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
5 Meneo Johnson

Si bien este ejemplo puede parecer un poco superfluo, dado que ya tenemos una columna de clave principal, puede haber instancias en las que prefiera usar el rowid . El rowid puede ser útil si no puede usar la columna de clave principal por algún motivo, o si la tabla no tiene una clave principal. Además, la documentación de Oracle menciona que rowid los valores son la forma más rápida de acceder a una sola fila.

Opción 6

Y aquí está el otro ejemplo, pero con rowid en lugar de la clave principal:

DELETE FROM Dogs
WHERE rowid > (
  SELECT MIN(rowid) FROM Dogs d2  
  WHERE Dogs.FirstName = d2.FirstName
  AND Dogs.LastName = d2.LastName
);

SELECT * FROM Dogs;

Resultado:

DOGID NOMBRE APELLIDO
1 Ladrar Smith
3 Guau Jones
4 Ruff Robinson
5 Meneo Johnson