Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

4 modi per verificare la presenza di righe duplicate in SQL Server

Di seguito sono riportati quattro metodi che puoi utilizzare per trovare righe duplicate in SQL Server.

Per "righe duplicate" intendo due o più righe che condividono esattamente gli stessi valori su tutte le colonne.

Dati campione

Supponiamo di avere una tabella con i seguenti dati:

SELECT * FROM Pets;

Risultato:

+---------+-----------+-----------+
| PetId   | PetName   | PetType   |
|---------+-----------+-----------|
| 1       | Wag       | Dog       |
| 1       | Wag       | Dog       |
| 2       | Scratch   | Cat       |
| 3       | Tweet     | Bird      |
| 4       | Bark      | Dog       |
| 4       | Bark      | Dog       |
| 4       | Bark      | Dog       |
+---------+-----------+-----------+

Possiamo vedere che le prime due righe sono duplicate, così come le ultime tre righe.

Opzione 1

Possiamo utilizzare la seguente query per restituire informazioni sulle righe duplicate:

SELECT 
    DISTINCT PetId, 
    COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;

Risultato:

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

Possiamo espandere il SELECT elenco per includere più colonne se necessario:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
ORDER BY PetId;

Risultato:

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

Se la tabella ha un identificatore univoco, possiamo semplicemente rimuovere quella colonna dalla query. Ad esempio, se assumiamo che PetId colonna è in realtà una colonna della chiave primaria che contiene un ID univoco, potremmo eseguire la seguente query per restituire tutte le righe duplicate, senza contare la colonna della chiave primaria:

SELECT 
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetName,
    PetType
ORDER BY PetName;

Risultato:

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

Opzione 2

Se desideriamo che vengano restituite solo le effettive righe duplicate, possiamo aggiungere HAVING clausola:

SELECT 
    PetId,
    PetName,
    PetType,
    COUNT(*) AS "Count"
FROM Pets
GROUP BY 
    PetId,
    PetName,
    PetType
HAVING COUNT(*) > 1
ORDER BY PetId;

Risultato:

+---------+-----------+-----------+---------+
| PetId   | PetName   | PetType   | Count   |
|---------+-----------+-----------+---------|
| 1       | Wag       | Dog       | 2       |
| 4       | Bark      | Dog       | 3       |
+---------+-----------+-----------+---------+

Opzione 3

Un altro modo per farlo è usare ROW_NUMBER() funzione con il PARTITION BY clausola per numerare l'output del set di risultati.

SELECT 
    *, 
    ROW_NUMBER() OVER ( 
        PARTITION BY PetId, PetName, PetType 
        ORDER BY PetId, PetName, PetType
        ) AS Row_Number
FROM Pets;

Risultato:

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

Il PARTITION BY La clausola divide il set di risultati prodotto dal FROM clausola in partizioni a cui viene applicata la funzione. Quando specifichiamo le partizioni per il set di risultati, ogni partizione fa ricominciare la numerazione (cioè la numerazione inizierà da 1 per la prima riga in ogni partizione).

Opzione 4

Se desideriamo che vengano restituite solo le righe in eccesso dai duplicati corrispondenti, possiamo utilizzare la query precedente come espressione di tabella comune, come questa:

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;

Risultato:

+---------+-----------+-----------+--------------+
| PetId   | PetName   | PetType   | Row_Number   |
|---------+-----------+-----------+--------------|
| 1       | Wag       | Dog       | 2            |
| 4       | Bark      | Dog       | 2            |
| 4       | Bark      | Dog       | 3            |
+---------+-----------+-----------+--------------+

Uno dei vantaggi di questa operazione è che possiamo eliminare le righe duplicate semplicemente cambiando SELECT * a DELETE (nell'ultima riga).

Pertanto possiamo utilizzare il codice sopra per vedere quali righe verranno eliminate, e quindi quando siamo soddisfatti di eliminare le righe corrette, possiamo cambiarlo in un DELETE dichiarazione per eliminarli effettivamente.

In questo modo:

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;