Las siguientes consultas se pueden usar para devolver filas duplicadas en SQLite.
Aquí, las filas duplicadas contienen valores duplicados en todas las columnas, incluida la columna ID.
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. Eso es porque las tres columnas contienen los mismos valores en cada fila duplicada.
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
Aquí, agrupamos las filas por todas las columnas y devolvimos el recuento de filas de cada grupo. Esto nos dice si una fila es única (con un recuento de 1) o un duplicado (con un recuento superior a 1).
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 PetId;
Resultado:
PetId PetName PetType Count ----- ------- ------- ----- 1 Wag Dog 2 4 Bark Dog 3
Opción 3
Otra opción es usar el ROW_NUMBER()
función de ventana:
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
Resultado:
PetId PetName PetType Row_Number ----- ------- ------- ---------- 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
*,
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.
Esta consulta puede ser útil para mostrar cuántas filas se eliminarán de la tabla en una operación de eliminación de duplicados. En algunos otros DBMS (al menos en SQL Server), podemos reemplazar el último SELECT *
con DELETE
para eliminar las filas duplicadas de la tabla. Pero SQLite no nos permitirá actualizar el CTE de esa manera.
Afortunadamente, las siguientes dos opciones se pueden modificar para realizar una eliminación.
Opción 5
Podemos aprovechar el rowid
de SQLite :
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
¿Como funciona esto? 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. Esto se puede eliminar si es necesario, pero a menos que se haya eliminado explícitamente, podrá aprovecharlo en sus consultas.
Opción 6
Y finalmente, aquí hay otra opción que usa el rowid
de SQLite :
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