103 votes

Supprimer les enregistrements en double dans SQL Server?

Prenons une colonne nommée EmployeeName table Employee . L'objectif est de supprimer les enregistrements répétés, en fonction du champ EmployeeName .

 EmployeeName
------------
Anand
Anand
Anil
Dipak
Anil
Dipak
Dipak
Anil
 

En utilisant une requête, je veux supprimer les enregistrements qui sont répétés.

Comment cela peut-il être fait avec TSQL dans SQL Server?

243voto

John Gibb Points 4473

Vous pouvez le faire avec des fonctions de fenêtre. Il ordonnera les dupes par empId et supprimera tout sauf le premier.

 delete x from (
  select *, rn=row_number() over (partition by EmployeeName order by empId)
  from Employee 
) x
where rn > 1;
 

Exécutez-le en tant que sélection pour voir ce qui serait supprimé:

 select *
from (
  select *, rn=row_number() over (partition by EmployeeName order by empId)
  from Employee 
) x
where rn > 1;
 

40voto

StuartLC Points 35534

En supposant que votre table Employee a également une colonne unique (ID dans l'exemple ci-dessous), le travail:

delete from Employee 
where ID not in
(
    select min(ID)
    from Employee 
    group by EmployeeName 
);

Cela laissera la version avec le plus bas de l'ID dans la table.

Modifier
Re McGyver du commentaire de SQL 2012

MIN peut être utilisé avec le numérique, char, varchar, de type uniqueidentifier, ou des colonnes datetime, mais pas avec les colonnes de bit

Pour 2008 R2 et les versions antérieures,

MIN peut être utilisé avec le numérique, de type char, varchar ou des colonnes datetime, mais pas avec les colonnes de bit (et elle aussi ne fonctionne pas avec un GUID)

Pour 2008R2 vous aurez besoin de jeter l' GUID pour un type pris en charge par MIN, par exemple

delete from GuidEmployees
where CAST(ID AS binary(16)) not in
(
    select min(CAST(ID AS binary(16)))
    from GuidEmployees
    group by EmployeeName 
);

SqlFiddle pour divers types de Sql 2008

SqlFiddle de différents types dans Sql 2012

8voto

Ben Cawley Points 985

Vous pouvez essayer quelque chose comme ce qui suit:

 delete T1
from MyTable T1, MyTable T2
where T1.dupField = T2.dupField
and T1.uniqueField > T2.uniqueField  
 

(cela suppose que vous ayez un champ unique basé sur un nombre entier)

Personnellement, je dirais que vous feriez mieux d'essayer de corriger le fait que des entrées en double sont ajoutées à la base de données avant qu'elle ne se produise, plutôt que comme une opération post-correction.

3voto

SubPortal Points 1016
 WITH CTE AS
(
   SELECT EmployeeName, 
          ROW_NUMBER() OVER(PARTITION BY EmployeeName ORDER BY EmployeeName) AS R
   FROM employee_table
)
DELETE CTE WHERE R > 1;
 

La magie des expressions de table communes.

3voto

Kumar Manish Points 1270
 DELETE
FROM MyTable
WHERE ID NOT IN (
     SELECT MAX(ID)
     FROM MyTable
     GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
 
 WITH TempUsers (FirstName, LastName, duplicateRecordCount)
AS
(
    SELECT FirstName, LastName,
    ROW_NUMBER() OVER (PARTITIONBY FirstName, LastName ORDERBY FirstName) AS duplicateRecordCount
    FROM dbo.Users
)
DELETE
FROM TempUsers
WHERE duplicateRecordCount > 1
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X