web-dev-qa-db-fra.com

Supprimer des lignes en double de redshift

J'essaie de supprimer des données en double dans ma table redshift.

Ci-dessous ma requête: -

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 ;

Cette requête me donne une erreur. 

Opération Amazon non valide: erreur de syntaxe proche de "delete";

Je ne sais pas quel est le problème, car la syntaxe de la clause with semble être correcte… Est-ce que quelqu'un a déjà affronté cette situation?

14
Neil

Redshift étant ce qu’il est (pas d’unicité imposée pour une colonne), la 3ème option de Ziggy est probablement la meilleure. Une fois que nous décidons d’utiliser la table de travail temporaire, il est plus efficace d’échanger des éléments entiers. Les suppressions et les insertions sont coûteuses dans 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;

Si l'espace n'est pas un problème, vous pouvez conserver l'ancienne table pendant un certain temps et utiliser les autres méthodes décrites ici pour valider que le nombre de lignes dans la comptabilisation d'origine des doublons correspond au nombre de lignes du nouveau.

Si vous chargez constamment une telle table, vous voudrez mettre ce processus en pause.

Si le nombre de doublons représente un faible pourcentage d'une table volumineuse, vous pouvez essayer de copier des enregistrements distincts des doublons dans une table temporaire, puis supprimer tous les enregistrements de l'original qui se joignent au fichier temporaire. Puis annexer la table temporaire à l’original. Assurez-vous de vider la table d'origine après (ce que vous devriez faire de toute façon pour les tables volumineuses).

18
systemjack

Si vous traitez beaucoup de données, il n'est pas toujours possible ni intelligent de recréer la table entière. Il peut être plus facile de localiser, supprimer ces lignes:

-- 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;

Article complet: https://elliot.land/post/removing-duplicate-data-in-redshift

8
Elliot Chance

Ce qui suit supprime tous les enregistrements de 'nomtable' qui ont un doublon, il ne dédupliquera pas la table:

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);

Extraits administratifs de Postgres

3
Phil Scalo

Cela aurait dû fonctionner. Alternative que vous pouvez faire:

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);

ou

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);

Si vous n'avez pas de clé primaire, vous pouvez effectuer les opérations suivantes:

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;

Réponse simple à cette question:

  1. Commencez par créer une table temporaire à partir de la table principale où la valeur de row_number=1.
  2. Deuxièmement delete toutes les lignes de la table principale sur lesquelles nous avons eu des doublons.
  3. Ensuite, insérez les valeurs de la table temporaire dans la table principale.

Requêtes:

  1. Table temporaire

    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. supprimer toutes les lignes de la table principale.

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

  3. insérer toutes les valeurs de la table temporaire dans la table principale 

    insert into table a select * from #temp_a.

2
Shivam Tyagi

Votre requête ne fonctionne pas car Redshift n'autorise pas DELETE après la clause WITH. Seuls SELECT et UPDATE et quelques autres sont autorisés (voir WITH clause )

Solution (dans ma situation):

Ma table events contenait une colonne id contenant des lignes en double et identifiant de manière unique l’enregistrement. Cette colonne id est identique à votre record_indicator.

Malheureusement, je n'ai pas pu créer de table temporaire car j'ai rencontré l'erreur suivante avec SELECT DISTINCT:

ERROR: Intermediate result row exceeds database block size

Mais cela a fonctionné comme un charme:

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

résultant dans la table temp:

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

Vous pouvez maintenant supprimer les doublons en supprimant les lignes dont la variable rownumber est supérieure à 1:

DELETE FROM temp WHERE rownumber > 1

Après cela, renommez les tables et vous avez terminé.

1
Matthijs