PostgreSQL 8.3.8データベースにテーブルがあり、キー/制約がなく、まったく同じ値の複数の行があります。
すべての重複を削除して、各行のコピーを1つだけ保持したいと思います。
特に、「キー」という名前の列が1つあり、重複を識別するために使用できます(つまり、「キー」ごとに1つのエントリのみが存在する必要があります)。
これどうやってするの?(理想的には単一のSQLコマンドを使用)この場合、速度は問題になりません(数行しかない)。
PostgreSQL 8.3.8データベースにテーブルがあり、キー/制約がなく、まったく同じ値の複数の行があります。
すべての重複を削除して、各行のコピーを1つだけ保持したいと思います。
特に、「キー」という名前の列が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
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
詳細については、一意の識別子なしで重複行を削除する方法の私の回答も参照してください。
ctid
は、テーブル内のレコードの物理的な場所を指します。当時私がコメントで書いたものとは逆に、ctが折り返されたり、ctidが低い値の方が実際には新しい場合があるため、小なり演算子を使用しても必ずしも古いバージョンを指すとは限りません。
min(ctid)
ますか?あなたのものは新しいものを保持しているのですか?ありがとう!
私はこれを試しました:
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によって提供されます:
id
含まれている場合は機能しません。
id
column1 ... 3が重複する最初の場所が保持されます
私は自分のバージョンを作成する必要がありました。@a_horse_with_no_nameによって書き込まれたバージョンは、私のテーブル(2100万行)では非常に低速です。そして、@ 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
ます。
DROP TABLE IF EXISTS tmp; CREATE TABLE tmp as ( SELECT * from (SELECT DISTINCT * FROM your_table) as t ); DELETE from your_table; INSERT INTO your_table SELECT * from tmp; DROP TABLE tmp;
別のアプローチ(id
テーブルのように一意のフィールドがある場合にのみ機能します)で列ごとにすべての一意のIDを検索し、一意のリストにない他のIDを削除
DELETE
FROM users
WHERE users.id NOT IN (SELECT DISTINCT ON (username, email) id FROM users);
どうですか:
と u AS(SELECT DISTINCT * FROM your_table)、 x AS(your_tableから削除) INSERT INTO your_table SELECT * FROM u;に挿入します。
私は実行順序を心配していましたが、DELETEはSELECT DISTINCTの前に発生しますが、私には問題なく動作しました。また、テーブル構造についての知識を必要としないという追加のボーナスがあります。
json
)がある場合、これが機能しないことです。
これは私にはうまくいきました。重複する値を含むテーブル、termsがありました。クエリを実行して、重複するすべての行を一時テーブルに入力します。次に、一時テーブルのIDを使用して削除ステートメントを実行しました。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)