Aquí hay siete formas de devolver filas duplicadas en MariaDB cuando esas filas tienen una clave principal u otra columna de identificador único.
Por lo tanto, las filas duplicadas comparten exactamente los mismos valores en todas las columnas excepto en su columna de identificador único.
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 que normalmente es bueno en los RDBMS. Sin embargo, por definición esto significa que no hay duplicados. En nuestro caso, 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 columnas que son significativo.
Opción 1
Podemos usar el 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;
Resultado:
+-----------+----------+-------+ | FirstName | LastName | Count | +-----------+----------+-------+ | Bark | Smith | 2 | | Ruff | Robinson | 1 | | Wag | Johnson | 3 | | Woof | Jones | 1 | +-----------+----------+-------+
Pudimos excluir la columna de clave principal al omitirla de nuestra consulta.
El resultado nos dice que hay dos filas que contienen a Bark Smith y tres filas que contienen a Wag Johnson. Estos son duplicados (o triplicados en el caso de Wag Johnson). Las otras dos filas no tienen duplicados.
Opción 2
Podemos excluir los no duplicados de la salida con HAVING
cláusula:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;
Resultado:
+-----------+----------+-------+ | FirstName | LastName | Count | +-----------+----------+-------+ | Bark | Smith | 2 | | Wag | Johnson | 3 | +-----------+----------+-------+
Opción 3
También es posible buscar duplicados en columnas concatenadas. Por ejemplo, podemos usar CONCAT()
función para concatenar nuestras dos columnas, use el DISTINCT
palabra clave para obtener valores distintos, luego use COUNT()
función para devolver el conteo:
SELECT
DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);
Resultado:
+---------------+-------+ | DogName | Count | +---------------+-------+ | Bark Smith | 2 | | Ruff Robinson | 1 | | Wag Johnson | 3 | | Woof Jones | 1 | +---------------+-------+
Opción 4
Podemos usar el ROW_NUMBER()
función con la PARTITION BY
cláusula:
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 | | 6 | Wag | Johnson | 1 | | 5 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | | 3 | Woof | Jones | 1 | +-------+-----------+----------+------------+
Esto crea una nueva columna con un número de fila que aumenta cada vez que hay un duplicado, pero se reinicia cuando hay una fila única.
En este caso, no estamos agrupando los resultados, lo que significa que podemos ver cada fila duplicada, incluida su columna de identificador único.
Opción 5
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 | | 5 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | +-------+-----------+----------+------------+
Esto excluye los no duplicados de la salida y excluye una fila de cada duplicado de la salida.
Esta consulta podría usarse como precursora de una operación de eliminación de duplicados. Puede mostrarnos qué se va a eliminar si decidimos eliminar los duplicados. Para deduplicar la tabla, todo lo que tenemos que hacer es reemplazar el último SELECT *
con DELETE
.
Opción 6
Aquí hay una forma más sucinta 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 | +-------+-----------+----------+
Este ejemplo no requiere generar nuestro propio número de fila por separado.
Podemos reemplazar SELECT *
con DELETE
para eliminar los duplicados.
Opción 7
Y finalmente, aquí hay otra opción para devolver duplicados:
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 | +-------+-----------+----------+-------+-----------+----------+