2017-10-21 3 views
0

重複した行を削除するのが難しいです。私はuser_idとtime_idが一緒に識別子として働いていると思っていましたが、それらの重複もありました。ポストグルで重複を削除する方法(一意のIDなし)

USER_ID(テキスト)、TIME_ID(BIGINT)、私は重複を削除するにはどのようにこの場合

user_id; time_id; value1| 
aaa;1;3| 
aaa;1;3| 
aaa;2;4| 
baa;3;1| 

(数値)をvalue1?私はTIME_IDで16の異なる値とのuser_idで15,000の異なるものを持っているので 、私はこのような何かを試してみましたが、私は一意のIDを持っていない...

DELETE FROM tablename a 
    USING tablename b 
    WHERE a.unique_id < b.unique_id 
    AND a.user_id = b.user_id 
    time_id = 1  (repeat till time_id 16) 
+0

ほぼ常に*のように、Postgresのあなたのバージョンは本質的な詳細です。 –

答えて

1

はあなたのことを確認し、注意して削除上の任意のアドバイスを使用してください必要に応じて "元に戻す"方法があります。私はあなたがその後、私はあなたが(ここで、RN = 1)を保持したくない行を識別するのに役立つROW_NUMBER()を使用してお勧めするこの努力に

alter table tablename add column is_uniq serial 

を支援する自動番号の列を追加する必要があると思うし、それら削除する(rn> 1)。ガイドとして次を使用します。

select * 
    , ROW_NUMBER()over(partition by user_id, time_id, value1 order by is_uniq) as rn from tablename 

私が順に使用する任意の他の列(複数可)があるかどうかわからないんだけど、その後がある場合は、同様句以上にそれを含めることができます。

「is_uniq」列とrn> 1行を取得したら、不要な行を安全に削除できるはずです。

+0

そして*最初にテーブルをバックアップする*。 '\ copy tablename 'に' tablename-before-delete.csv''を 'psql'で使うのは簡単な方法です。 –

2

Postgresの各テーブルには、いくつかの非表示のsystem columnsがあります。そのうちの1つである(ctid)は定義上一意であり、主キーがない場合に使用できます。

DELETE FROM tablename a 
USING tablename b 
WHERE a.ctid < b.ctid 
AND a.user_id = b.user_id 
AND a.time_id = b.time_id; 

問題はプライマリキーの不足によるものです。非表示の列を使用することは系統的な方法ではありません(下記のコメントを参照)。重複を削除したら、(user_id, time_id)に主キーを作成するか、この目的のために新しい一意の列を作成する必要があります。

+0

できますが、一般的ではありません。これはおそらく初心者のための最良のアドバイスではありませんが、完全に有効です。 –

+0

シンプルでクリアで*完全に有効な*なぜ使用しないのですか? – klin

+0

'ctid'は実際にはパブリックインタフェースではないので、非標準的な実装の詳細です。また、PostgreSQLの将来のリリースでは、このクエリを徹底的に、あるいはそれ以上に微妙に壊すように変更することはありません。 –

0

あなたはctid(個人的に、私はない)、あなたは(例えばserialなど)一意の列を追加することができますに依存しているとアイデンティティの目的のためにそれを使用したくない場合は、


CREATE TABLE lutser 
     (user_id text not null 
     , time_i integer not null 
     , value integer not null 
     ); 
INSERT INTO lutser(user_id,time_i,value) VALUES 
('aaa', 1, 3) 
,('aaa', 1, 3) 
,('aaa', 2, 4) 
,('baa', 3, 1) 
     ; 

SELECT*FROM lutser; 

ALTER TABLE lutser 
     ADD COLUMN seq serial NOT NULL UNIQUE 
     ; 
SELECT*FROM lutser; 

DELETE FROM lutser del 
WHERE EXISTS(
     SELECT*FROM lutser x 
     WHERE x.user_id=del.user_id 
     AND x.time_i=del.time_i 
     AND x.seq < del.seq 
     ); 

ALTER TABLE lutser 
     ADD PRIMARY KEY (user_id,time_i) 
     ; 

SELECT*FROM lutser; 
関連する問題