web-dev-qa-db-ja.com

Redshiftから重複行を削除する

Redshiftテーブルの重複データを削除しようとしています。

以下は私のクエリです:-

With duplicates
As
(Select *, ROW_NUMBER() Over (PARTITION by record_indicator Order by record_indicator) as Duplicate From table_name)
delete from duplicates
Where Duplicate > 1 ;

このクエリによりエラーが発生します。

Amazonの無効な操作:「delete」またはその近くの構文エラー。

With節の構文が正しいと思われるため、問題が何であるかはわかりません。誰も以前にこの状況に直面したことがありますか?

15
Neil

Redshiftがそのままの状態(どの列にも一意性が強制されない)であるため、Ziggyの3番目のオプションがおそらく最適です。一時テーブルルートに進むと決めたら、全体を入れ替える方が効率的です。 Redshiftでは、削除と挿入は負荷がかかります。

begin;
create table table_name_new as select distinct * from table_name;
alter table table_name rename to table_name_old;
alter table table_name_new rename to table_name;
drop table table_name_old;
commit;

スペースが問題にならない場合は、古いテーブルをしばらく保持し、ここで説明する他の方法を使用して、重複の元のアカウンティングの行数が新しいテーブルの行数と一致することを検証できます。

そのようなテーブルに対して一定のロードを実行している場合、これが進行している間はそのプロセスを一時停止する必要があります。

重複の数が大きなテーブルのわずかな割合である場合、重複の個別のレコードを一時テーブルにコピーしてから、一時と結合するすべてのレコードを元から削除することをお勧めします。次に、 追加 一時テーブルを元に戻します。 vacuum の後に元のテーブルがあることを確認してください(とにかくスケジュールに沿って大きなテーブルに対して行うべきです)。

18
systemjack

大量のデータを扱っている場合、テーブル全体を再作成することは常に可能または賢いわけではありません。これらの行を見つけて削除する方が簡単かもしれません:

-- First identify all the rows that are duplicate
CREATE TEMP TABLE duplicate_saleids AS
SELECT saleid
FROM sales
WHERE saledateid BETWEEN 2224 AND 2231
GROUP BY saleid
HAVING COUNT(*) > 1;

-- Extract one copy of all the duplicate rows
CREATE TEMP TABLE new_sales(LIKE sales);

INSERT INTO new_sales
SELECT DISTINCT *
FROM sales
WHERE saledateid BETWEEN 2224 AND 2231
AND saleid IN(
     SELECT saleid
     FROM duplicate_saleids
);

-- Remove all rows that were duplicated (all copies).
DELETE FROM sales
WHERE saledateid BETWEEN 2224 AND 2231
AND saleid IN(
     SELECT saleid
     FROM duplicate_saleids
);

-- Insert back in the single copies
INSERT INTO sales
SELECT *
FROM new_sales;

-- Cleanup
DROP TABLE duplicate_saleids;
DROP TABLE new_sales;

COMMIT;

完全な記事: https://elliot.land/post/removing-duplicate-data-in-redshift

13
Elliot Chance

うまくいったはずです。あなたができる代替:

With 
  duplicates As (
    Select *, ROW_NUMBER() Over (PARTITION by record_indicator
                                 Order by record_indicator) as Duplicate
    From table_name)
delete from table_name
where id in (select id from duplicates Where Duplicate > 1);

または

delete from table_name
where id in (
  select id
  from (
    Select id, ROW_NUMBER() Over (PARTITION by record_indicator
                                 Order by record_indicator) as Duplicate
    From table_name) x
  Where Duplicate > 1);

主キーがない場合は、次を実行できます。

BEGIN;
CREATE TEMP TABLE mydups ON COMMIT DROP AS
  SELECT DISTINCT ON (record_indicator) *
  FROM table_name
  ORDER BY record_indicator --, other_optional_priority_field DESC
;

DELETE FROM table_name
WHERE record_indicator IN (
  SELECT record_indicator FROM mydups);

INSERT INTO table_name SELECT * FROM mydups;
COMMIT;

以下は、重複している 'tablename'のすべてのレコードを削除し、テーブルの重複を削除しません:

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管理スニペット

3
Phil Scalo

この質問に対する簡単な答え:

  1. まず、メインテーブルから一時テーブルを作成します。ここで、row_number=1
  2. 次に、delete重複したメインテーブルのすべての行。
  3. 次に、一時テーブルの値をメインテーブルに挿入します。

クエリ:

  1. 一時テーブル

    select id,date into #temp_a from (select *
    from (select a.*, row_number() over(partition by id order by etl_createdon desc) as rn from table a where a.id between 59 and 75 and a.date = '2018-05-24') where rn =1)a

  2. メインテーブルからすべての行を削除します。

    delete from table a where a.id between 59 and 75 and a.date = '2018-05-24'

  3. すべての値を一時テーブルからメインテーブルに挿入する

    insert into table a select * from #temp_a

3
Shivam Tyagi

RedshiftはDELETE句の後のWITHを許可しないため、クエリは機能しません。許可されるのはSELECTUPDATEおよび他のいくつかのみです( WITH句 を参照)

ソリューション(私の状況では):

テーブルにid列がありましたeventsには重複する行が含まれており、レコードを一意に識別します。この列idは、record_indicatorと同じです。

残念ながら、SELECT DISTINCTを使用して次のエラーが発生したため、一時テーブルを作成できませんでした。

ERROR: Intermediate result row exceeds database block size

しかし、これは魅力のように機能しました:

CREATE TABLE temp as (
    SELECT *,ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS rownumber 
    FROM events
);

tempテーブルになります:

id | rownumber | ...
----------------
1  | 1         | ...
1  | 2         | ...
2  | 1         | ...
2  | 2         | ...

これで、rownumberが1より大きい行を削除することで、重複を削除できます。

DELETE FROM temp WHERE rownumber > 1

その後、テーブル名と完了名を変更します。

1
Matthijs