Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

4 maneiras de encontrar linhas duplicadas no MySQL


Se você acha que uma tabela MySQL pode ter linhas duplicadas, você pode usar as seguintes opções para retornar todas as duplicatas.

Dados de amostra


Suponha que temos uma tabela com os seguintes dados:
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     |
+-------+---------+---------+

As duas primeiras linhas são duplicadas, assim como as três últimas linhas. As linhas duplicadas compartilham os mesmos valores em todas as colunas.

Opção 1


Uma opção é usar a seguinte consulta para retornar linhas duplicadas:
SELECT 
    DISTINCT PetId, 
    COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;

Resultado:
+-------+-------+
| PetId | Count |
+-------+-------+
|     1 |     2 |
|     2 |     1 |
|     3 |     1 |
|     4 |     3 |
+-------+-------+

Podemos expandir o SELECT list para incluir mais colunas, se necessário:
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 |
+-------+---------+---------+-------+

Podemos fazer com que as duplicatas apareçam primeiro ordenando-as por contagem em ordem decrescente:
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 |
+-------+---------+---------+-------+

Opção 2


Se quisermos apenas listar as linhas duplicadas, podemos usar o HAVING cláusula para excluir não duplicados da saída:
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 |
+-------+---------+---------+-------+

Opção 3


Outra maneira de fazer isso é usar o ROW_NUMBER() função com a função PARTITION BY cláusula para numerar a saída do conjunto de resultados.
SELECT 
    *, 
    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 |
+-------+---------+---------+----+

A PARTITION BY cláusula divide o conjunto de resultados produzido pelo FROM cláusula em partições às quais a função é aplicada. Quando especificamos partições para o conjunto de resultados, cada partição faz com que a numeração comece novamente (ou seja, a numeração começará em 1 para a primeira linha de cada partição).

Opção 4


Para retornar apenas as linhas excedentes das duplicatas correspondentes, podemos usar a consulta acima como uma expressão de tabela comum, assim:
WITH cte AS 
    (
        SELECT 
            *, 
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS rn
        FROM Pets
    )
SELECT * FROM cte WHERE rn <> 1;

Resultado:
+-------+---------+---------+----+
| PetId | PetName | PetType | rn |
+-------+---------+---------+----+
|     1 | Wag     | Dog     |  2 |
|     4 | Bark    | Dog     |  2 |
|     4 | Bark    | Dog     |  3 |
+-------+---------+---------+----+