2010-07-23 7 views
70

Considérons une colonne nommée EmployeeName table Employee. L'objectif est de supprimer les enregistrements répétés, en fonction du champ EmployeeName.Supprimer les enregistrements en double dans SQL Server?

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?

+0

Vous voulez supprimer les enregistrements en double, n'est-ce pas? – Sarfraz

+0

vous pouvez sélectionner les valeurs distinctes et leurs ID associés et supprimer les enregistrements dont les ID ne figurent pas dans la liste déjà sélectionnée? – DaeMoohn

+1

avez-vous une colonne d'identifiant unique? –

Répondre

158

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écuter comme une 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; 
+0

très intelligent .... –

+2

Si vous n'avez pas de clé primaire, vous pouvez utiliser 'ORDER BY (SELECT NULL)' http://stackoverflow.com/a/4812038 – Arithmomaniac

7

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 avez un entier basé champ unique)

Personnellement si je dirais que vous étiez mieux essayer de corriger le fait que les entrées en double sont ajoutées à la base de données avant qu'elle ne se produise plutôt qu'en tant qu'opération post-réparation.

+0

Je n'ai pas le champ unique (ID) dans mon Table. Comment puis-je effectuer l'opération alors. – usr021986

27

En supposant que votre table des employés a également une colonne unique, (ID dans l'exemple ci-dessous), ce qui suit fonctionnera:

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

Cela laissera la version avec le plus bas ID dans le tableau.

Modifier
Commentaire de Re McGyver - au SQL 2012

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

Pour 2008 R2 et avant,

MIN peut être utilisé avec numérique, char, varchar ou colonnes datetime, mais pas avec des colonnes de bits (et il ne fonctionne pas non plus avec son GUID)

Pour 2008R2, vous aurez besoin de jeter la GUID à 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 for various types in Sql 2008

SqlFiddle for various types in Sql 2012

+0

En outre, dans Oracle, vous pouvez utiliser "rowid" s'il n'y a pas d'autre colonne d'identifiant unique. –

+0

+1 Même s'il n'y avait pas de colonne d'identifiant, on pourrait en ajouter un comme champ d'identité. –

2
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 commune.

+0

SubPortal/a_horse_with_no_name - ne devrait-il pas être sélectionnant à partir d'une table réelle? En outre, ROW_NUMBER doit être ROW_NUMBER() parce que c'est une fonction, correct? – MacGyver

2
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 
1

Essayez

DELETE 
FROM employee 
WHERE rowid NOT IN (SELECT MAX(rowid) FROM employee 
GROUP BY EmployeeName); 
1

Si vous êtes à la recherche d'un moyen de supprimer les doublons, mais vous avez un pointage de clé étrangère à la table avec les doublons, vous pouvez prendre la approche suivante en utilisant un curseur lent mais efficace.

Il va déplacer les clés dupliquées sur la table de clé étrangère.

create table #properOlvChangeCodes(
    id int not null, 
    name nvarchar(max) not null 
) 

DECLARE @name VARCHAR(MAX); 
DECLARE @id INT; 
DECLARE @newid INT; 
DECLARE @oldid INT; 

DECLARE OLVTRCCursor CURSOR FOR SELECT id, name FROM Sales_OrderLineVersionChangeReasonCode; 
OPEN OLVTRCCursor; 
FETCH NEXT FROM OLVTRCCursor INTO @id, @name; 
WHILE @@FETCH_STATUS = 0 
BEGIN 
     -- determine if it should be replaced (is already in temptable with name) 
     if(exists(select * from #properOlvChangeCodes where [email protected])) begin 
      -- if it is, finds its id 
      Select top 1 @newid = id 
      from Sales_OrderLineVersionChangeReasonCode 
      where Name = @name 

      -- replace terminationreasoncodeid in olv for the new terminationreasoncodeid 
      update Sales_OrderLineVersion set ChangeReasonCodeId = @newid where ChangeReasonCodeId = @id 

      -- delete the record from the terminationreasoncode 
      delete from Sales_OrderLineVersionChangeReasonCode where Id = @id 
     end else begin 
      -- insert into temp table if new 
      insert into #properOlvChangeCodes(Id, name) 
      values(@id, @name) 
     end 

     FETCH NEXT FROM OLVTRCCursor INTO @id, @name; 
END; 
CLOSE OLVTRCCursor; 
DEALLOCATE OLVTRCCursor; 

drop table #properOlvChangeCodes 
-1

Veuillez également consulter la méthode de suppression ci-dessous.

Declare @Employee table (EmployeeName varchar(10)) 

Insert into @Employee values 
('Anand'),('Anand'),('Anil'),('Dipak'), 
('Anil'),('Dipak'),('Dipak'),('Anil') 

Select * from @Employee 

enter image description here

créé un exemple de tableau nommé @Employee et chargé avec les données fournies.

Delete aliasName from (
Select *, 
     ROW_NUMBER() over (Partition by EmployeeName order by EmployeeName) as rowNumber 
From @Employee) aliasName 
Where rowNumber > 1 

Select * from @Employee 

Résultat:

enter image description here

Je sais, cela est demandé il y a six ans, l'affichage juste Incase il est utile pour tout le monde.

Questions connexes