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

6 formas de seleccionar filas duplicadas en Oracle

Los siguientes ejemplos devuelven filas duplicadas de una tabla de Oracle Database.

Datos de muestra

Supongamos que tenemos una tabla con los siguientes datos:

SELECT * FROM Pets;

Resultado:

PetId  PetName  PetType
-----  -------  -------
1      Wag      Dog    
1      Wag      Dog    
2      Scratch  Cat    
3      Tweet    Bird   
4      Bark     Dog    
4      Bark     Dog    
4      Bark     Dog    

Las dos primeras filas son duplicados, al igual que las últimas tres filas. En este caso, las filas duplicadas contienen valores duplicados en todas las columnas, incluida la columna ID.

Opción 1

Podemos usar la siguiente consulta para ver cuántas filas están duplicadas:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY PetId;

Resultado:

PETID	PETNAME	PETTYPE	Count
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	3

Agrupamos las filas por todas las columnas y devolvimos el recuento de filas de cada grupo. Cualquier fila con un recuento superior a 1 es un duplicado.

Podemos ordenarlo por conteo en orden descendente, de modo que las filas con más duplicados aparezcan primero:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY Count(*) DESC;

Resultado:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1

Opción 2

Si solo queremos que se enumeren las filas duplicadas, podemos usar HAVING cláusula para devolver solo filas con un recuento mayor que 1:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC;

Resultado:

PETID	PETNAME	PETTYPE	Count
4	Bark	Dog	3
1	Wag	Dog	2

Opción 3

Otra opción es usar el ROW_NUMBER() función de ventana:

SELECT 
    PetId,
    PetName,
    PetType,
    ROW_NUMBER() OVER ( 
        PARTITION BY PetId, PetName, PetType 
        ORDER BY PetId, PetName, PetType
        ) AS rn
FROM Pets;

Resultado:

PETID	PETNAME	PETTYPE	RN
1	Wag	Dog	1
1	Wag	Dog	2
2	Scratch	Cat	1
3	Tweet	Bird	1
4	Bark	Dog	1
4	Bark	Dog	2
4	Bark	Dog	3

La PARTITION BY cláusula divide el conjunto de resultados producido por FROM cláusula en particiones a las que se aplica la función. Cuando especificamos particiones para el conjunto de resultados, cada partición hace que la numeración comience de nuevo (es decir, la numeración comenzará en 1 para la primera fila de cada partición).

Opción 4

Podemos usar la consulta anterior como una expresión de tabla común:

WITH cte AS 
    (
        SELECT 
            PetId,
            PetName,
            PetType,
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Resultado:

PETID	PETNAME	PETTYPE	ROW_NUMBER
1	Wag	Dog	2
4	Bark	Dog	2
4	Bark	Dog	3

Esto devuelve solo el exceso de filas de los duplicados coincidentes. Entonces, si hay dos filas idénticas, devuelve una de ellas. Si hay tres filas idénticas, devuelve dos, y así sucesivamente.

Opción 5

Dado que nuestra tabla no contiene una columna de clave principal, podemos aprovechar el rowid de Oracle pseudocolumna:

SELECT * FROM Pets
WHERE EXISTS (
  SELECT 1 FROM Pets p2 
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
  AND Pets.rowid > p2.rowid
);

Resultado:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

La forma en que esto funciona es que cada fila en una base de datos 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. Sin embargo, es importante tener en cuenta que las filas en diferentes tablas que se almacenan juntas en el mismo clúster pueden tener el mismo rowid .

Un beneficio del ejemplo anterior es que podemos reemplazar SELECT * con DELETE para deduplicar la tabla.

Opción 6

Y finalmente, aquí hay otra opción que usa el rowid pseudocolumna:

SELECT * FROM Pets
WHERE rowid > (
  SELECT MIN(rowid) FROM Pets p2  
  WHERE Pets.PetName = p2.PetName
  AND Pets.PetType = p2.PetType
);

Resultado:

PETID	PETNAME	PETTYPE
1	Wag	Dog
4	Bark	Dog
4	Bark	Dog

Mismo resultado que el ejemplo anterior.

Como en el ejemplo anterior, podemos reemplazar SELECT * con DELETE para eliminar filas duplicadas de la tabla.