Hier zijn vier methoden die u kunt gebruiken om dubbele rijen in SQL Server te vinden.
Met 'dubbele rijen' bedoel ik twee of meer rijen die exact dezelfde waarden in alle kolommen delen.
Voorbeeldgegevens
Stel dat we een tabel hebben met de volgende gegevens:
SELECT * FROM Pets;
Resultaat:
+---------+-----------+-----------+ | PetId | PetName | PetType | |---------+-----------+-----------| | 1 | Wag | Dog | | 1 | Wag | Dog | | 2 | Scratch | Cat | | 3 | Tweet | Bird | | 4 | Bark | Dog | | 4 | Bark | Dog | | 4 | Bark | Dog | +---------+-----------+-----------+
We kunnen zien dat de eerste twee rijen duplicaten zijn, net als de laatste drie rijen.
Optie 1
We kunnen de volgende query gebruiken om informatie over dubbele rijen te retourneren:
SELECT
DISTINCT PetId,
COUNT(*) AS "Count"
FROM Pets
GROUP BY PetId
ORDER BY PetId;
Resultaat:
+---------+---------+ | PetId | Count | |---------+---------| | 1 | 2 | | 2 | 1 | | 3 | 1 | | 4 | 3 | +---------+---------+
We kunnen de SELECT
. uitbreiden lijst om indien nodig meer kolommen op te nemen:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
ORDER BY PetId;
Resultaat:
+---------+-----------+-----------+---------+ | PetId | PetName | PetType | Count | |---------+-----------+-----------+---------| | 1 | Wag | Dog | 2 | | 2 | Scratch | Cat | 1 | | 3 | Tweet | Bird | 1 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+---------+
Als de tabel een unieke id heeft, kunnen we die kolom eenvoudig uit de query verwijderen. Als we bijvoorbeeld aannemen dat de PetId
kolom in feite een primaire-sleutelkolom is die een unieke ID bevat, kunnen we de volgende query uitvoeren om alle rijen te retourneren die duplicaten zijn, de primaire-sleutelkolom niet meegerekend:
SELECT
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetName,
PetType
ORDER BY PetName;
Resultaat:
+-----------+-----------+---------+ | PetName | PetType | Count | |-----------+-----------+---------| | Bark | Dog | 3 | | Scratch | Cat | 1 | | Tweet | Bird | 1 | | Wag | Dog | 2 | +-----------+-----------+---------+
Optie 2
Als we alleen de daadwerkelijke dubbele rijen willen retourneren, kunnen we de HAVING
. toevoegen clausule:
SELECT
PetId,
PetName,
PetType,
COUNT(*) AS "Count"
FROM Pets
GROUP BY
PetId,
PetName,
PetType
HAVING COUNT(*) > 1
ORDER BY PetId;
Resultaat:
+---------+-----------+-----------+---------+ | PetId | PetName | PetType | Count | |---------+-----------+-----------+---------| | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+---------+
Optie 3
Een andere manier om dit te doen is door de ROW_NUMBER()
. te gebruiken functie met de PARTITION BY
clausule om de uitvoer van de resultaatset te nummeren.
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY PetId, PetName, PetType
ORDER BY PetId, PetName, PetType
) AS Row_Number
FROM Pets;
Resultaat:
+---------+-----------+-----------+--------------+ | 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 | +---------+-----------+-----------+--------------+
De PARTITION BY
clausule verdeelt de resultaatset geproduceerd door de FROM
clausule in partities waarop de functie wordt toegepast. Wanneer we partities specificeren voor de resultatenset, zorgt elke partitie ervoor dat de nummering opnieuw begint (d.w.z. de nummering begint bij 1 voor de eerste rij in elke partitie).
Optie 4
Als we alleen overtollige rijen van de overeenkomende duplicaten willen retourneren, kunnen we de bovenstaande query gebruiken als een algemene tabeluitdrukking, zoals deze:
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;
Resultaat:
+---------+-----------+-----------+--------------+ | PetId | PetName | PetType | Row_Number | |---------+-----------+-----------+--------------| | 1 | Wag | Dog | 2 | | 4 | Bark | Dog | 2 | | 4 | Bark | Dog | 3 | +---------+-----------+-----------+--------------+
Een van de voordelen hiervan is dat we dubbele rijen kunnen verwijderen door simpelweg SELECT *
te wisselen om DELETE
(op de laatste regel).
Daarom kunnen we de bovenstaande code gebruiken om te zien welke rijen worden verwijderd, en als we er dan zeker van zijn dat we de juiste rijen gaan verwijderen, kunnen we deze overschakelen naar een DELETE
statement om ze daadwerkelijk te verwijderen.
Zoals dit:
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;