sql >> Databasteknik >  >> RDS >> Sqlserver

4 sätt att söka efter dubbletter av rader i SQL Server

Här är fyra metoder du kan använda för att hitta dubbletter av rader i SQL Server.

Med "dubbletter av rader" menar jag två eller flera rader som delar exakt samma värden i alla kolumner.

Exempeldata

Anta att vi har en tabell med följande data:

SELECT * FROM Pets;

Resultat:

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

Vi kan se att de två första raderna är dubbletter, liksom de tre sista raderna.

Alternativ 1

Vi kan använda följande fråga för att returnera information om dubbletter av rader:

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

Resultat:

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

Vi kan utöka SELECT lista för att inkludera fler kolumner om det behövs:

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

Resultat:

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

Om tabellen har en unik identifierare kan vi helt enkelt ta bort den kolumnen från frågan. Till exempel, om vi antar att PetId kolumnen är faktiskt en primärnyckelkolumn som innehåller ett unikt ID, vi skulle kunna köra följande fråga för att returnera alla rader som är dubbletter, utan att räkna med primärnyckelkolumnen:

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

Resultat:

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

Alternativ 2

Om vi ​​bara vill att de faktiska dubblettraderna ska returneras kan vi lägga till HAVING klausul:

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

Resultat:

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

Alternativ 3

Ett annat sätt att göra det är att använda ROW_NUMBER() funktion med PARTITION BY sats för att numrera resultatet av resultatuppsättningen.

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

Resultat:

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

PARTITION BY satsen delar resultatuppsättningen som produceras av FROM sats i partitioner som funktionen tillämpas på. När vi anger partitioner för resultatuppsättningen, gör varje partition att numreringen börjar om igen (dvs. numreringen börjar på 1 för den första raden i varje partition).

Alternativ 4

Om vi ​​bara vill att överskottsrader från de matchande dubbletterna ska returneras, kan vi använda ovanstående fråga som ett vanligt tabelluttryck, så här:

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;

Resultat:

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

En av fördelarna med att göra detta är att vi kan ta bort dubbletter av rader helt enkelt genom att byta SELECT * till DELETE (på sista raden).

Därför kan vi använda ovanstående kod för att se vilka rader som kommer att raderas, och när vi sedan är övertygade om att vi ska ta bort rätt rader kan vi byta den till en DELETE uttalande för att faktiskt ta bort dem.

Så här:

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;

  1. MySQL SELECT senaste dagarna?

  2. SQL-ändringstabell

  3. Rownum i postgresql

  4. Mönstermatchning:Roligare när jag var barn