sqlite 데이터베이스에서 중복 행 삭제


91

SQLite3에 3 천 6 백만 행의 거대한 테이블이 있습니다. 이 매우 큰 테이블에는 두 개의 열이 있습니다.

  • hash -텍스트
  • d -진짜

일부 행이 중복됩니다. 즉, 모두 hashd같은 값을 가지고있다. 두 해시가 동일하면의 값도 동일합니다 d. 그러나 두 개의 동일한 d'이 두 개의 동일한 '을 의미하지는 않습니다 hash.

중복 된 행을 삭제하고 싶습니다. 기본 키 열이 없습니다.

이를 수행하는 가장 빠른 방법은 무엇입니까?


답안 블록에 답을 넣으십시오. 나중에 자신의 답변을 수락 할 수 있습니다. 답변 수락
jww

답변:


121

행을 구별하는 방법이 필요합니다. 귀하의 의견에 따라 특수 rowid 열 을 사용할 수 있습니다 .

가장 낮은 유지하여 중복을 삭제하려면 rowid당을 (hash,d):

delete   from YourTable
where    rowid not in
         (
         select  min(rowid)
         from    YourTable
         group by
                 hash
         ,       d
         )

SQLite는 기본 키 열을 추가하도록 허용하지 않습니다.
패치

sqlite> alter table dist add id integer primary key autoincrement; Error: Cannot add a PRIMARY KEY column
패치

흥미 롭군요! 필요한 부분은 autoincrement그래도 primary key부분 을 생략하면 작동 합니까?
Andomar 2011

sqlite> alter table dist add id integer autoincrement; Error: near "autoincrement": syntax error 편집 : SQLite에는 자동으로 존재하는 "rowid"유사 열 유형이 있습니다. 이것을 사용할 수 있습니까?
패치

1
delete from dist where rowid not in (select max(rowid) from dist group by hash); 트릭을 할 것 같습니다! 감사.
패치

5

가장 빠른 방법은 바로 데이터베이스를 사용하는 것입니다. 동일한 열이있는 새 테이블을 추가하고 적절한 제약 조건 (해시 / 실제 쌍에 대한 고유 인덱스?)을 사용하고 원래 테이블을 반복하고 레코드를 삽입하려고합니다. 제약 위반 오류를 무시하는 새 테이블 (예 : 예외가 발생할 때 계속 반복)

그런 다음 이전 테이블을 삭제하고 새 테이블을 이전 테이블로 이름을 바꿉니다.


단순히 테이블을 변경하는 것만 큼 우아하지는 않지만 접근 방식에서 정말 좋은 점은 결과에 절대적으로 만족할 때까지 소스 데이터를 건드 리거나 파괴하지 않고 원하는만큼 다시 실행할 수 있다는 것입니다. .
Adrian K

1

기본 키를 추가하는 것이 옵션이 아닌 경우 한 가지 방법은 중복 DISTINCT를 임시 테이블에 저장하고 기존 테이블에서 모든 중복 레코드를 삭제 한 다음 임시 테이블에서 원래 테이블에 레코드를 다시 추가하는 것입니다. .

예 (SQL Server 2008 용으로 작성되었지만 기술은 모든 데이터베이스에서 동일 함) :

DECLARE @original AS TABLE([hash] varchar(20), [d] float)
INSERT INTO @original VALUES('A', 1)
INSERT INTO @original VALUES('A', 2)
INSERT INTO @original VALUES('A', 1)
INSERT INTO @original VALUES('B', 1)
INSERT INTO @original VALUES('C', 1)
INSERT INTO @original VALUES('C', 1)

DECLARE @temp AS TABLE([hash] varchar(20), [d] float)
INSERT INTO @temp
SELECT [hash], [d] FROM @original 
GROUP BY [hash], [d]
HAVING COUNT(*) > 1

DELETE O
FROM @original O
JOIN @temp T ON T.[hash] = O.[hash] AND T.[d] = O.[d]

INSERT INTO @original
SELECT [hash], [d] FROM @temp

SELECT * FROM @original

sqlite에 ROW_NUMBER()유형 함수 가 있는지 확실 하지 않지만 여기에 나열된 방법 중 일부를 시도해 볼 수도 있습니다. 기본 키없이 SQL 테이블에서 중복 레코드 삭제


+1, sqlite가 delete <alias> from <table> <alias>구문을 지원하는지 확실하지 않음
Andomar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.