[sql] PostgreSQL에서 중복 레코드 삭제

PostgreSQL 8.3.8 데이터베이스에 키 / 제약 조건이없고 정확히 동일한 값을 가진 여러 행이있는 테이블이 있습니다.

모든 중복을 제거하고 각 행의 사본을 1 개만 유지하고 싶습니다.

특히 중복을 식별하는 데 사용할 수있는 하나의 열 ( “키”라고 함)이 있습니다 (즉, 각 고유 “키”에 대해 하나의 항목 만 있어야 함).

어떻게 할 수 있습니까? (이상적으로는 단일 SQL 명령 사용)이 경우 속도는 문제가되지 않습니다 (행이 몇 개만 있음).



답변

DELETE FROM dupes a
WHERE a.ctid <> (SELECT min(b.ctid)
                 FROM   dupes b
                 WHERE  a.key = b.key);


답변

더 빠른 솔루션은

DELETE FROM dups a USING (
      SELECT MIN(ctid) as ctid, key
        FROM dups
        GROUP BY key HAVING COUNT(*) > 1
      ) b
      WHERE a.key = b.key
      AND a.ctid <> b.ctid


답변

이것은 빠르고 간결합니다.

DELETE FROM dupes T1
    USING   dupes T2
WHERE   T1.ctid < T2.ctid  -- delete the older versions
    AND T1.key  = T2.key;  -- add more columns if needed

자세한 정보를 포함하는 고유 식별자없이 중복 행을 삭제하는 방법의 내 대답을 참조하십시오.


답변

나는 이것을 시도했다 :

DELETE FROM tablename
WHERE id IN (SELECT id
              FROM (SELECT id,
                             ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum
                     FROM tablename) t
              WHERE t.rnum > 1);

Postgres 위키에서 제공 :

https://wiki.postgresql.org/wiki/Deleting_duplicates


답변

나만의 버전을 만들어야했습니다. @a_horse_with_no_name에 의해 작성된 버전은 내 테이블에서 너무 느립니다 (21M 행). 그리고 @rapimo는 단순히 dups를 삭제하지 않습니다.

PostgreSQL 9.5에서 사용하는 것은 다음과 같습니다.

DELETE FROM your_table
WHERE ctid IN (
  SELECT unnest(array_remove(all_ctids, actid))
  FROM (
         SELECT
           min(b.ctid)     AS actid,
           array_agg(ctid) AS all_ctids
         FROM your_table b
         GROUP BY key1, key2, key3, key4
         HAVING count(*) > 1) c);


답변

임시 테이블을 사용합니다.

create table tab_temp as
select distinct f1, f2, f3, fn
  from tab;

그런 다음, 삭제 tab및 이름 변경 tab_temptab.


답변

id열별로 모든 고유 ID를 찾고 고유 목록에없는 다른 ID를 제거하는 또 다른 방법 ( 테이블에 있는 고유 필드가있는 경우에만 작동 )

DELETE
FROM users
WHERE users.id NOT IN (SELECT DISTINCT ON (username, email) id FROM users);