Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

4 maneiras de verificar linhas duplicadas no SQL Server


Aqui estão quatro métodos que você pode usar para localizar linhas duplicadas no SQL Server.

Por “linhas duplicadas” quero dizer duas ou mais linhas que compartilham exatamente os mesmos valores em todas as colunas.

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       |
+---------+-----------+-----------+

Podemos ver que as duas primeiras linhas são duplicadas, assim como as três últimas linhas.

Opção 1


Podemos usar a seguinte consulta para retornar informações sobre 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       |
+---------+-----------+-----------+---------+

Se a tabela tiver um identificador exclusivo, podemos simplesmente remover essa coluna da consulta. Por exemplo, se assumirmos que o PetId column é na verdade uma coluna de chave primária que contém um ID exclusivo, poderíamos executar a seguinte consulta para retornar todas as linhas duplicadas, sem contar a coluna de chave primária:
SELECT 
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetName,
    PetType
ORDER BY PetName;

Resultado:
+-----------+-----------+---------+
| PetName   | PetType   | Count   |
|-----------+-----------+---------|
| Bark      | Dog       | 3       |
| Scratch   | Cat       | 1       |
| Tweet     | Bird      | 1       |
| Wag       | Dog       | 2       |
+-----------+-----------+---------+

Opção 2


Se quisermos apenas as linhas duplicadas reais retornadas, podemos adicionar o HAVING cláusula:
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 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            |
+---------+-----------+-----------+--------------+

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


Se quisermos que apenas as linhas excedentes das duplicatas correspondentes sejam retornadas, 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 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            |
+---------+-----------+-----------+--------------+

Um dos benefícios de fazer isso é que podemos excluir linhas duplicadas simplesmente alternando SELECT * para DELETE (na última linha).

Portanto, podemos usar o código acima para ver quais linhas serão excluídas e, quando estivermos convencidos de que vamos excluir as linhas corretas, podemos alterná-lo para um DELETE instrução para realmente excluí-los.

Assim:
WITH CTE AS 
    (
        SELECT 
            *, 
            ROW_NUMBER() OVER ( 
                PARTITION BY PetId, PetName, PetType 
                ORDER BY PetId, PetName, PetType
                ) AS Row_Number
        FROM Pets
    )
DELETE FROM CTE WHERE Row_Number <> 1;