Удаление истинных дубликатов из таблицы Greenplum - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь удалить истинные дубликаты из таблицы.В прошлом я несколько раз удалял дубликаты, но я не могу понять, что не так с моим синтаксисом.

Мой код -

DELETE 
FROM   my_table_name 
WHERE  ( 
              column1, column2, column3, column4, column5, column6, column7, column8, column9) IN
       ( 
                SELECT   Row_number() OVER( partition BY column1, column2,column3, column4,column5,column6,column7,column8 ORDER BY column2 DESC, column3 ASC ) AS row_num,
                         column1, 
                         column2, 
                         column3, 
                         column4, 
                         column5, 
                         column6, 
                         column7, 
                         column8, 
                         column9 
                FROM     my_table_name 
                WHERE    column1='some_value') a 
WHERE  row_num=2;

Ошибка

********** Error **********

ERROR: syntax error at or near ""a""
SQL state: 42601
Character: 1607

Я вижу, что ошибка возникает при создании псевдонима a .Но я не могу точно определить, что здесь не так.

Любая помощь приветствуется


Редактировать 1 - Если я удалю a , я получу следующееошибка

********** Error **********

ERROR: syntax error at or near "where"
SQL state: 42601
Character: 1608

1 Ответ

0 голосов
/ 27 марта 2019

Если у вас есть повторяющиеся строки, вы не можете просто удалить все, кроме одной записи, в одной команде. Вы должны удалить все дубликаты и затем вставить только одну версию для каждой дублирующейся строки или построить новую таблицу (предпочтительно) без дубликатов.

Давайте начнем с предпочтительного метода, который заключается в создании новой таблицы без дубликатов. Это решение использует дисковое пространство наиболее эффективным способом, чем использование фрагментированной таблицы.

Пример:

create table foo
(id int, fname text)
with (appendonly=true)
distributed by (id);

Вставьте некоторые данные с дубликатами:

insert into foo values (1, 'jon');
insert into foo values (1, 'jon');
insert into foo values (2, 'bill');
insert into foo values (2, 'bill');
insert into foo values (3, 'sue');
insert into foo values (4, 'ted');
insert into foo values (4, 'ted');
insert into foo values (4, 'ted');
insert into foo values (4, 'ted');

Создать новую версию таблицы без дубликатов:

create table foo_new with (appendonly=true) as
select id, fname
from (
    select row_number() over (partition by id) as row_num, id, fname
    from foo
    ) as sub
where sub.row_num = 1
distributed by (id);

А теперь переименуйте таблицы:

alter table foo rename to foo_old;
alter table foo_new rename to foo;

Второй метод заключается в использовании DELETE, но вы увидите, что для его завершения требуется больше шагов.

Сначала создайте временную таблицу с идентификаторами, которые вы хотите удалить. Обычно в Greenplum первичные ключи не применяются, но у вас все еще есть логический PK. Такие столбцы, как customer_id, product_id и т. Д., Находятся в ваших данных. Итак, сначала найдите дупы на основе PK.

drop table if exists foo_pk_delete;
create temporary table foo_pk_delete with (appendonly=true) as
select id
from foo
group by id
having count(*) > 1
distributed by (id);

Далее, получите всю строку для каждого дубликата, но только одну его версию.

drop table if exists foo_dedup;
create temporary table foo_dedup with (appendonly=true) as
select id, fname
from (
    select row_number() over (partition by f.id) as row_num, f.id, f.fname
    from foo f 
    join foo_pk_delete fd on f.id = fd.id
    ) as sub
where sub.row_num = 1
distributed by (id);

Теперь вы можете удалить дубликаты:

delete 
from foo f
using foo_pk_delete fk 
where f.id = fk.id;

И затем вы можете вставить дедуплицированные данные обратно в таблицу.

insert into foo (id, fname)
select id, fname from foo_dedup;

Вы захотите очистить свой стол после этой манипуляции с данными.

vacuum foo;
...