2010-07-23 19 views
70

Rozważ kolumnę o nazwie EmployeeName Tabela Employee. Celem jest usunięcie powtarzających się rekordów, w oparciu o pole EmployeeName.Usunąć zduplikowane rekordy w SQL Server?

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

Używając jednego zapytania, chcę usunąć powtarzające się rekordy.

Jak to zrobić z TSQL na serwerze SQL?

+0

Masz na myśli usunąć duplikaty rekordów, prawda? – Sarfraz

+0

można wybrać różne wartości i powiązane z nimi identyfikatory i usunąć te rekordy, których identyfikatory nie znajdują się na już wybranej liście? – DaeMoohn

+1

Czy masz unikalną kolumnę ID? –

Odpowiedz

158

Można to zrobić za pomocą funkcji okna. Zamówi duplikaty według empID i usunie wszystkie oprócz pierwszego.

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

uruchomić go jako wybierz, aby zobaczyć, co będzie usunięte:

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

bardzo sprytny .... –

+2

Jeśli nie masz klucza podstawowego, możesz użyć opcji "ORDER BY (WYBIERZ NULL)" http://stackoverflow.com/a/4812038 – Arithmomaniac

7

Można spróbować coś jak następuje:

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

(zakładając, że masz całkowitą oparciu unikalny pola)

Osobiście choć powiedziałbym, że byli lepiej próbuje skorygować fakt że zduplikowane wpisy są dodawane do bazy danych przed jej wystąpieniem, a nie jako operacja post-it-it.

+0

Mam donot mieć unikalne pole (ID) w moim Stół. Jak mogę wtedy wykonać operację. – usr021986

27

Zakładając, że tabela Pracownik ma również unikalną kolumnę (ID w poniższym przykładzie) dodaje zadziała:

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

Pozostawi wersję z najniższym ID w tabeli.

Edit komentarz
Re mcgyver - stan z SQL 2012

MIN może być używany z numerycznym, char, varchar, uniqueidentifier lub kolumn datetime, ale nie z bitowych kolumn

Dla 2008 R2 i wcześniejszych,

MIN może być używany z numeryczna, char, varchar, lub kolumny datetime, ale nie z bitowych kolumn (i to też nie działa na GUID)

Dla 2008R2 musisz rzucać GUID na typ obsługiwany przez MIN, np.

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

Również w Oracle można użyć "rowid", jeśli nie ma innej unikalnej kolumny id. –

+0

+1 Nawet jeśli nie ma kolumny ID, można dodać pole tożsamości. –

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; 

Magia typowych wyrażeń tabeli.

+0

SubPortal/a_horse_with_no_name - nie powinno to być wybierając z rzeczywistego stołu? Ponadto ROW_NUMBER powinien mieć wartość ROW_NUMBER(), ponieważ jest to funkcja, prawda? – 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

Spróbuj

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

Jeśli szukasz sposobu na usuwanie duplikatów, jeszcze masz klucza obcego wskazującego stole z duplikatów, można podjąć następujące podejście przy użyciu powolnego, ale efektywnego kursora.

Po przeniesieniu duplikatów klawiszy na tabeli kluczy obcych.

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

Proszę zobaczyć poniższy sposób usuwania.

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

utworzono przykładową tabelę o nazwie @Employee i załadowaniu go z podanych danych.

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

Select * from @Employee 

Wynik:

enter image description here

wiem, to proszony jest o sześć lat temu, publikując tylko okrywać jest pomocne dla każdego.

Powiązane problemy