2010-07-23 6 views
70

EmployeeName 테이블 Employee이라는 열을 고려하십시오. 목표는 EmployeeName 필드를 기반으로 반복 기록을 삭제하는 것입니다.SQL Server에서 중복 레코드를 삭제 하시겠습니까?

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

하나의 쿼리를 사용하여 반복되는 레코드를 삭제하고 싶습니다.

SQL Server에서 TSQL을 사용하여 어떻게 수행 할 수 있습니까?

+0

중복 된 레코드를 삭제한다는 뜻인가요? – Sarfraz

+0

고유 값 및 관련 ID를 선택하고 ID가 이미 선택된 목록에없는 레코드를 삭제할 수 있습니까? – DaeMoohn

+1

고유 ID 열이 있습니까? –

답변

158

당신은 윈도우 기능이 작업을 수행 할 수 있습니다. 그것은 empId에 의해 속임수를 주문하고 첫 번째 것을 제외하고 모두 삭제할 것입니다. 선별로

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

실행이 삭제 될 것을 확인하려면 다음을 참조하십시오 :

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

매우 똑똑합니다 .... –

+2

기본 키가 없으면 'ORDER BY (SELECT NULL)'을 사용할 수 있습니다. http://stackoverflow.com/a/4812038 – Arithmomaniac

7

당신은 뭔가를 시도 할 수 다음

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

(이 가정 당신은 정수를 기반으로 고유의 필드 가지고) 나는 당신이 사실을 해결하기 위해 노력하고 더 잘했다라고 말하고 싶지만하지만 개인적으로

을 중복 항목은 수정 수정 작업 이후가 아닌 데이터베이스에 추가됩니다.

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

이 테이블에서 가장 낮은 ID와 버전을 떠날 것이다 :

+0

고유 한 필드 (ID)가 없습니다. 표. 그럼 어떻게해야할까요? – usr021986

27

, 다음이 작동됩니다 Employee 테이블은 또한 고유의 열 (아래의 예 ID)가 있다고 가정.
다시 McGyver의 의견

편집 - 비트 열로 SQL 2012

MIN의이 숫자, CHAR, VARCHAR, 고유 식별자, 또는 날짜 열을 사용할 수 있습니다,하지만

2008 R2 이하의 경우

MIN 당신이 캐스팅해야하지만 비트 열 을 (그리고 그것은 또한 GUID의 작동하지 않습니다) 2008R2를 들어

와 숫자, 문자, varchar 또는 날짜 열을 사용할 수 있습니다 GUID에서 MIN으로 지원되는 유형으로

SqlFiddle for various types in Sql 2008

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 2012

+0

또한 다른 고유 ID 열이없는 경우 Oracle에서 "rowid"를 사용할 수 있습니다. –

+0

+1 ID 열이없는 경우에도 신원 필드로 추가 할 수 있습니다. –

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; 

공통 테이블 식의 마법.

+0

SubPortal/a_horse_with_no_name - 그렇게해서는 안됩니다. 실제 테이블에서 선택 하시겠습니까? 또한 ROW_NUMBER은 (는) 함수이기 때문에 ROW_NUMBER() 여야합니다. 맞습니까? – 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

당신은 중복을 제거 할 수있는 방법을 찾고 있다면

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

을 시도, 아직 중복과 테이블에 외래 키 포인팅을 가지고, 당신은 걸릴 수 있습니다 느리고 효과적인 커서를 사용하는 접근 방식.

외부 키 테이블의 중복 키를 재배치합니다.

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

아래 삭제 방법도 참조하십시오.

enter image description here

Declare @Employee table (EmployeeName varchar(10)) 

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

Select * from @Employee 
@Employee라는 이름의 샘플 테이블을 작성하고 주어진 데이터를로드.

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

Select * from @Employee 

결과는 :

enter image description here

내가 아는이는 누군가를 위해 도움이 그냥 넣다 게시, 6 년 전 요청합니다.

관련 문제