PostgreSQL 8.3.8データベースにテーブルがあり、そのテーブルにはキー/制約がなく、まったく同じ値を持つ複数の行があります。
すべての重複を削除し、各行のコピーを1つだけ保持したいと思います。
重複を識別するために使用できる特定の列(「キー」)があります(つまり、各「キー」ごとに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 wikiにより提供:
独自のバージョンを作成する必要がありました。 @a_horse_with_no_nameによって記述されたバージョンは、テーブル(21M行)で非常に遅いです。また、@ rapimoは重複を削除しません。
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_temp
の名前をtab
に変更します。
これは私にとってはうまくいきました。重複した値を含む用語、テーブルがありました。クエリを実行して、すべての重複行を一時テーブルに追加します。次に、一時テーブルにこれらのIDを指定してdeleteステートメントを実行しました。 valueは、重複を含む列です。
CREATE TEMP TABLE dupids AS
select id from (
select value, id, row_number()
over (partition by value order by value)
as rownum from terms
) tmp
where rownum >= 2;
delete from [table] where id in (select id from dupids)