2010-07-23 4 views
70

Si consideri una colonna denominata EmployeeName tabella Employee. L'obiettivo è eliminare i record ripetuti, in base al campo EmployeeName.Elimina record duplicati in SQL Server?

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

Utilizzando una query, desidero eliminare i record che si ripetono.

Come può essere fatto con TSQL in SQL Server?

+0

Vuoi dire eliminare i record duplicati, giusto? – Sarfraz

+0

è possibile selezionare i valori distinti e i relativi ID correlati ed eliminare quei record i cui ID non si trovano nell'elenco già selezionato? – DaeMoohn

+1

hai una colonna ID univoca? –

risposta

158

È possibile farlo con funzioni finestra. Ordinerà i duplicati con empId e cancellerà tutti tranne il primo.

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

Esegui come un prescelto per vedere quello che sarebbe stato cancellato:

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

molto intelligente .... –

+2

Se non si dispone di una chiave primaria, è possibile utilizzare 'ORDER BY (SELECT NULL)' http://stackoverflow.com/a/4812038 – Arithmomaniac

7

Si potrebbe provare qualcosa di simile al seguente:

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

(questo presuppone che si dispone di una base di campo unico intero)

Personalmente, però direi che eri meglio cercando di correggere il fatto che le voci duplicate vengono aggiunte al database prima che si verifichi piuttosto che come un'operazione di post-fix.

+0

I donot avere il campo unico (ID) nel mio Tavolo. Come posso eseguire l'operazione allora. – usr021986

27

Supponendo che la tabella Employee ha anche una colonna unica (ID nell'esempio qui sotto), il seguente funziona:

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

questo lascerà la versione con l'ID più basso nella tabella.

Modifica commento di
Re McGyver - come di SQL 2012

MIN può essere utilizzato con numerico, char, varchar, uniqueidentifier, o colonne datetime, ma non con le colonne bit

Per 2008 R2 e precedenti,

MIN può essere utilizzato con numerico, char, varchar o colonne datetime, ma non con le colonne bit (e anche non funziona con GUID)

Per 2008R2 è necessario lanciare il GUID a un tipo supportato da MIN, ad es.

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

Inoltre, in Oracle, è possibile utilizzare "rowid" se non esiste un'altra colonna id univoca. –

+0

+1 Anche se non ci fosse una colonna ID, si potrebbe aggiungere uno come campo di 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 magia di espressioni di tabella comuni.

+0

SubPortal/a_horse_with_no_name - non dovrebbe essere questo selezionando da una tabella reale? Inoltre, ROW_NUMBER deve essere ROW_NUMBER() perché è una funzione, corretta? – 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

Prova

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

Se siete alla ricerca di un modo per rimuovere i duplicati, ma si dispone di una chiave esterna che punta alla tabella con i duplicati, si potrebbe prendere il seguendo l'approccio usando un cursore lento ma efficace.

Sarà riposizionare le chiavi duplicate sul tavolo chiave esterna.

-1

Vedere anche la modalità di cancellazione qui sotto.

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

Creato una tabella di esempio denominata @Employee e caricato con dati forniti.

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

Select * from @Employee 

Risultato:

enter image description here

lo so, questo viene chiesto sei anni fa, inviando solo in caso è utile per chiunque.