Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Oorspronkelijke productversie: SQL Server
Oorspronkelijk KB-nummer: 70956
Samenvatting
In dit artikel wordt beschreven hoe u dubbele rijen uit een tabel in Microsoft SQL Server verwijdert met behulp van een T-SQL-script (Transact-SQL). Er worden twee veelvoorkomende methoden beschreven: één exemplaar van elke dubbele rij naar een afzonderlijke tabel kopiëren en de ROW_NUMBER functie gebruiken om de extra rijen ter plekke te verwijderen. Gebruik dit artikel als een tabel herhaalde records bevat, bijvoorbeeld omdat deze geen unieke beperking of primaire sleutel heeft. Methode 2 is eenvoudiger omdat deze in-place werkt.
Een voorbeeldtabel maken die dubbele rijen bevat
Als u beide methoden wilt demonstreren, maakt u een voorbeeldtabel met de naam original_table die één kolom heeft, key_value, en voegt u dubbele gegevens toe:
CREATE TABLE original_table (key_value int )
INSERT INTO original_table values (1)
INSERT INTO original_table values (1)
INSERT INTO original_table values (1)
INSERT INTO original_table values (2)
INSERT INTO original_table values (2)
INSERT INTO original_table values (2)
INSERT INTO original_table values (2)
Gebruik vervolgens een van de volgende methoden om de dubbele rijen uit de tabel te verwijderen.
Note
Met deze scripts worden gegevens definitief verwijderd. Maak een back-up van de tabel of database voordat u deze opdrachten uitvoert op productiegegevens.
Methode 1: Dubbele rijen naar een afzonderlijke tabel verplaatsen en één kopie opnieuw invoegen
Methode 1 maakt gebruik van twee tabellen: original_table en een tweede tabel, duplicate_tabledie door het script wordt gemaakt en vervolgens wordt verwijderd. Als u het script wilt toepassen op een andere tabel, vervangt u original_table door de tabelnaam. Voor deze methode moet de logica van GROUP BY en COUNT opnieuw worden geschreven als een duplicaat wordt gedefinieerd door meer dan één kolom.
Voer het volgende script uit:
SELECT DISTINCT *
INTO duplicate_table
FROM original_table
GROUP BY key_value
HAVING COUNT(key_value) > 1
DELETE original_table
WHERE key_value
IN (SELECT key_value
FROM duplicate_table)
INSERT original_table
SELECT *
FROM duplicate_table
DROP TABLE duplicate_table
Dit script voert de volgende acties uit in de gegeven volgorde:
- Verplaatst één exemplaar van een willekeurige dubbele rij in de oorspronkelijke tabel naar een dubbele tabel.
- Hiermee verwijdert u alle rijen uit de oorspronkelijke tabel die zich ook in de duplicaattabel bevinden.
- Hiermee verplaatst u de rijen in de duplicaattabel terug naar de oorspronkelijke tabel.
- Verwijdert de dubbele tabel.
Deze methode is eenvoudig. U moet echter voldoende ruimte in de database hebben om de dubbele tabel tijdelijk te bouwen. Deze methode veroorzaakt ook overhead omdat u de gegevens verplaatst.
Als uw tabel een identiteitskolom heeft, moet u SET IDENTITY_INSERT ON gebruiken wanneer u de gegevens terugzet naar de oorspronkelijke tabel.
Methode 2: Gebruik de functie ROW_NUMBER om dubbele rijen te verwijderen
De ROW_NUMBER functie, die is geïntroduceerd in Microsoft SQL Server 2005, maakt deze bewerking veel eenvoudiger. Vervang key_value door de kolom of kolommen die een duplicaat definiëren.
DELETE T
FROM
(
SELECT *
, DupRank = ROW_NUMBER() OVER (
PARTITION BY key_value
ORDER BY (SELECT NULL)
)
FROM original_table
) AS T
WHERE DupRank > 1
Dit script voert de volgende acties uit in de gegeven volgorde:
- Hiermee gebruikt u de
ROW_NUMBERfunctie om de gegevens te partitioneren op basis van dekey_value, die uit een of meer door komma's gescheiden kolommen kan bestaan. - Verwijdert alle records die een
DupRankwaarde hebben gekregen die groter is dan 1. Deze waarde geeft aan dat de records duplicaten zijn.
Vanwege de (SELECT NULL)-expressie sorteert het script de gepartitioneerde gegevens niet op basis van enige voorwaarde. Als voor uw logica voor het verwijderen van duplicaten moet worden gekozen welke records moeten worden verwijderd en welke records moeten worden behouden op basis van de sorteervolgorde van andere kolommen, kunt u de ORDER BY-expressie gebruiken om dit te doen.
De meest recente rij behouden wanneer u duplicaten verwijdert
Als u de rij met de meest recente waarde wilt behouden, sorteert u in aflopende volgorde op die kolom. Denk bijvoorbeeld aan een hypothetisch employee_table dat meer dan één rij voor dezelfde werknemer heeft. Met het volgende script blijft alleen de rij met de meest recente updated_date waarde behouden:
DELETE T
FROM
(
SELECT *
, DupRank = ROW_NUMBER() OVER (
PARTITION BY employee_name
ORDER BY updated_date DESC
)
FROM employee_table
) AS T
WHERE DupRank > 1
De rij met de meest recente updated_date waarde ontvangt een DupRank van 1, dus het script bewaart die en verwijdert de oudere rijen.
Waarom wordt methode 2 aanbevolen?
Methode 2 is eenvoudig en effectief om deze redenen:
- U hoeft de dubbele records niet tijdelijk naar een andere tabel te kopiëren.
- U hoeft de oorspronkelijke tabel niet met zichzelf samen te voegen (bijvoorbeeld door een subquery te gebruiken die alle dubbele records retourneert met behulp van een combinatie van
GROUP BYenHAVING). - Voor de beste prestaties moet u een bijbehorende index hebben op de tabel die gebruikmaakt van de
key_valueals indexsleutel en eventuele sorteerkolommen bevat die u mogelijk in deORDER BY-expressie hebt gebruikt.
De ROW_NUMBER functie is beschikbaar in SQL Server 2005 en nieuwere versies. Als u een versie van SQL Server gebruikt die de functie ROW_NUMBER niet ondersteunt, gebruikt u in plaats daarvan methode 1 of een vergelijkbare methode.
Hoe kan ik dubbele rijen in een tabel voorkomen?
Nadat u de duplicaten hebt verwijderd, kunt u nieuwe dubbele rijen voorkomen door een unique constraint of een unieke index te definiëren voor de kolom of kolommen die een rij identificeren.