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

4 måder at kontrollere for duplikerede rækker i SQL Server

Her er fire metoder, du kan bruge til at finde dublerede rækker i SQL Server.

Med "duplikerede rækker" mener jeg to eller flere rækker, der deler nøjagtig de samme værdier på tværs af alle kolonner.

Eksempeldata

Antag, at vi har en tabel med følgende 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, at de første to rækker er dubletter, ligesom de sidste tre rækker.

Valgmulighed 1

Vi kan bruge følgende forespørgsel til at returnere oplysninger om duplikerede rækker:

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 udvide SELECT liste for at inkludere flere kolonner, hvis det kræves:

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

Hvis tabellen har en unik identifikator, kan vi blot fjerne denne kolonne fra forespørgslen. For eksempel, hvis vi antager, at PetId kolonne er faktisk en primær nøglekolonne, der indeholder et unikt ID, kunne vi køre følgende forespørgsel for at returnere alle rækker, der er dubletter, uden at tælle primærnøglekolonnen med:

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

Valgmulighed 2

Hvis vi kun vil have de faktiske duplikerede rækker returneret, kan vi tilføje 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       |
+---------+-----------+-----------+---------+

Valgmulighed 3

En anden måde at gøre det på er at bruge ROW_NUMBER() funktion med PARTITION BY klausul for at nummerere outputtet af resultatsættet.

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 klausul deler resultatsættet produceret af FROM klausul i partitioner, som funktionen anvendes på. Når vi angiver partitioner for resultatsættet, får hver partition nummereringen til at starte forfra (dvs. nummereringen starter ved 1 for den første række i hver partition).

Valgmulighed 4

Hvis vi kun ønsker, at overskydende rækker fra de matchende dubletter skal returneres, kan vi bruge ovenstående forespørgsel som et almindeligt tabeludtryk, som dette:

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 af fordelene ved at gøre dette er, at vi kan slette duplikerede rækker blot ved at skifte SELECT * til DELETE (på sidste linje).

Derfor kan vi bruge ovenstående kode til at se, hvilke rækker der vil blive slettet, og når vi så er overbeviste om, at vi skal slette de korrekte rækker, kan vi skifte den til en DELETE erklæring for rent faktisk at slette dem.

Sådan:

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. Sådan fungerer CHAR_LENGTH() i MariaDB

  2. Hvordan udfører man den samme aggregering på hver kolonne uden at angive kolonnerne?

  3. Ændring af et Enum-felt ved hjælp af Alembic

  4. freeTDS bruger ikke sin konfiguration