[sql] SQL Server에서 중복 레코드를 삭제 하시겠습니까?

EmployeeNametable 이라는 열을 고려하십시오 Employee. 목표는 EmployeeName필드를 기반으로 반복되는 레코드를 삭제하는 것 입니다.

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

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

SQL Server에서 TSQL로 어떻게이 작업을 수행 할 수 있습니까?



답변

창 기능으로이를 수행 할 수 있습니다. 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;


답변

Employee 테이블에도 고유 한 열이 있다고 가정하면 ( ID아래 예에서) 다음이 작동합니다.

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

그러면 테이블에서 ID가 가장 낮은 버전이 남습니다.


Re McGyver의 주석 편집 -SQL 2012 기준

MIN numeric, char, varchar, uniqueidentifier 또는 datetime 열과 함께 사용할 수 있지만 비트 열에는 사용할 수 없습니다.

들어 2008 R2 및 이전 버전

MIN은 숫자, char, varchar 또는 datetime 열과 함께 사용할 수 있지만 비트 열에 는 사용할 수 없습니다 (GUID에서도 작동하지 않음).

2008R2 GUID의 경우에서 지원하는 유형 으로 캐스트해야합니다 MIN. 예 :

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

Sql 2008의 다양한 유형에 대한 SqlFiddle

Sql 2012의 다양한 유형에 대한 SqlFiddle


답변

다음과 같은 것을 시도 할 수 있습니다.

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

(이것은 정수 기반 고유 필드가 있다고 가정합니다)

개인적으로는 수정 후 작업보다는 중복 항목이 데이터베이스에 추가되기 전에 데이터베이스에 추가된다는 사실을 수정하는 것이 더 낫다고 말하고 싶습니다.


답변

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


답변

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

일반적인 테이블 표현식의 마법.


답변

시험

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


답변

중복을 제거하는 방법을 찾고 있지만 중복이있는 테이블을 가리키는 외래 키가있는 경우 느리지 만 효과적인 커서를 사용하여 다음 방법을 사용할 수 있습니다.

외래 키 테이블에서 중복 키를 재배치합니다.

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 Name=@name)) 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