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