sql >> Base de Datos >  >> RDS >> SQLite

11 formas de encontrar filas duplicadas ignorando la clave principal en SQLite

Aquí hay once opciones para devolver filas duplicadas en SQLite cuando esas filas tienen una clave principal o alguna otra columna de identificador único (pero desea ignorar la clave principal).

Esto significa que las filas duplicadas comparten exactamente los mismos valores en todas las columnas con la excepción de su clave principal/columna de ID única.

Datos de muestra

Usaremos los siguientes datos para nuestros ejemplos:

SELECT * FROM Dogs;

Resultado:

DogId  FirstName  LastName
-----  ---------  --------
1      Bark       Smith   
2      Bark       Smith   
3      Woof       Jones   
4      Ruff       Robinson
5      Wag        Johnson 
6      Wag        Johnson 
7      Wag        Johnson 

Las dos primeras filas son duplicados (excepto el DogId columna, que es la clave principal de la tabla y contiene un valor único en todas las filas). Las últimas tres filas también son duplicados (excepto el DogId columna).

La columna de clave principal garantiza que no haya filas duplicadas, lo cual es una buena práctica en RDBMS, porque las claves principales ayudan a reforzar la integridad de los datos. Pero debido a que las claves principales evitan filas duplicadas, tienen el potencial de interferir con nuestra capacidad para encontrar duplicados.

En nuestra tabla anterior, la columna de clave principal es un número creciente, y su valor no tiene ningún significado y no es significativo. Por lo tanto, debemos ignorar esa fila si queremos encontrar duplicados en las otras columnas.

Opción 1

Podemos ejecutar una consulta con GROUP BY cláusula para agrupar las columnas por sus columnas significativas, luego use el COUNT() función para devolver el número de filas idénticas:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
ORDER BY Count DESC;

Resultado:

FirstName  LastName  Count
---------  --------  -----
Wag        Johnson   3    
Bark       Smith     2    
Ruff       Robinson  1    
Woof       Jones     1    

Aquí excluimos la columna de clave principal al omitirla de nuestra consulta. También lo ordenamos por conteo en orden descendente, para que los duplicados aparezcan primero.

El resultado nos dice que hay tres filas que contienen a Wag Johnson y dos filas que contienen a Bark Smith. Estos son duplicados (o triplicados en el caso de Wag Johnson). Las otras dos filas no tienen duplicados.

Opción 2

Podemos usar el HAVING cláusula para excluir no duplicados de la salida:

SELECT 
    FirstName, 
    LastName, 
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1
ORDER BY Count DESC;

Resultado:

FirstName  LastName  Count
---------  --------  -----
Wag        Johnson   3    
Bark       Smith     2    

Opción 3

Este es un ejemplo de verificación de duplicados en columnas concatenadas. En este caso usamos el DISTINCT palabra clave para obtener valores distintos, luego use COUNT() función para devolver el conteo:

SELECT
    DISTINCT FirstName || ' ' || LastName AS DogName,
    COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName || ' ' || LastName
ORDER BY Count DESC;

Resultado:

DogName        Count
-------------  -----
Wag Johnson    3    
Bark Smith     2    
Woof Jones     1    
Ruff Robinson  1    

Opción 4

De forma predeterminada, cada fila en SQLite tiene una columna especial, generalmente llamada rowid , que identifica de forma única esa fila dentro de la tabla. A menos que se haya eliminado explícitamente de la tabla, puede usar esto como un identificador único para cada fila.

Por lo tanto, podemos usar el rowid en nuestra consulta:

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

Resultado:

DogId  FirstName  LastName
-----  ---------  --------
2      Bark       Smith   
6      Wag        Johnson 
7      Wag        Johnson 

Podríamos reemplazar el SELECT * con DELETE para realizar una operación de eliminación de duplicados en la tabla.

Tenga en cuenta que podríamos haber usado el DogId columna (nuestra clave principal) en lugar de rowid si quisiéramos. Dicho esto, 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.

Opción 5

Aquí hay otra consulta que usa el rowid :

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

Resultado:

DogId  FirstName  LastName
-----  ---------  --------
2      Bark       Smith   
6      Wag        Johnson 
7      Wag        Johnson 

Al igual que en el ejemplo anterior, podríamos reemplazar el SELECT * con DELETE para eliminar las filas duplicadas.

Opción 6

Los dos rowid Las opciones anteriores son excelentes si debe ignorar por completo la clave principal en su consulta (o si no tiene una columna de clave principal). Sin embargo, como se mencionó, todavía existe la opción de reemplazar rowid con la columna de la clave principal, en nuestro caso, el DogId columna:

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

Resultado:

DogId  FirstName  LastName
-----  ---------  --------
2      Bark       Smith   
6      Wag        Johnson 
7      Wag        Johnson 

Opción 7

Y aquí está la otra consulta con rowid reemplazado por el DogId columna:

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

Resultado:

DogId  FirstName  LastName
-----  ---------  --------
2      Bark       Smith   
6      Wag        Johnson 
7      Wag        Johnson 

Opción 8

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

SELECT 
    *,
    ROW_NUMBER() OVER ( 
        PARTITION BY FirstName, LastName 
        ORDER BY FirstName, LastName
        ) AS Row_Number
FROM Dogs;

Resultado:

DogId  FirstName  LastName  Row_Number
-----  ---------  --------  ----------
1      Bark       Smith     1         
2      Bark       Smith     2         
4      Ruff       Robinson  1         
5      Wag        Johnson   1         
6      Wag        Johnson   2         
7      Wag        Johnson   3         
3      Woof       Jones     1         

Usando la PARTITION La cláusula da como resultado que se agregue una nueva columna, con un número de fila que aumenta cada vez que hay un duplicado, pero se restablece nuevamente cuando hay una fila única.

En este caso, no agrupamos los resultados, lo que significa que podemos ver cada fila duplicada, incluida su columna de identificador único.

Opción 9

También podemos usar el ejemplo anterior como una expresión de tabla común en una consulta más grande:

WITH cte AS 
    (
        SELECT 
            *,
            ROW_NUMBER() OVER ( 
                PARTITION BY FirstName, LastName 
                ORDER BY FirstName, LastName
                ) AS Row_Number
        FROM Dogs
    )
SELECT * FROM cte WHERE Row_Number <> 1;

Resultado:

DogId  FirstName  LastName  Row_Number
-----  ---------  --------  ----------
2      Bark       Smith     2         
6      Wag        Johnson   2         
7      Wag        Johnson   3         

Eso excluye los no duplicados de la salida y excluye una fila de cada duplicado de la salida.

Opción 10

Aquí hay otra forma de obtener el mismo resultado que el ejemplo anterior:

SELECT * FROM Dogs 
WHERE DogId IN (
    SELECT DogId FROM Dogs 
    EXCEPT SELECT MIN(DogId) FROM Dogs 
    GROUP BY FirstName, LastName
    );

Resultado:

DogId  FirstName  LastName
-----  ---------  --------
2      Bark       Smith   
6      Wag        Johnson 
7      Wag        Johnson 

Opción 11

Aquí hay otra opción más para seleccionar duplicados de nuestra tabla:

SELECT * 
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
);

Resultado:

DogId  FirstName  LastName  DogId  FirstName  LastName
-----  ---------  --------  -----  ---------  --------
2      Bark       Smith     1      Bark       Smith   
7      Wag        Johnson   5      Wag        Johnson 
7      Wag        Johnson   6      Wag        Johnson