GP主要用於數據倉庫領域,在GP數據庫中,如果由於ETL重復跑數導致數據重復的話,就需要進行去重復操作。
一種方法是把某一時間段的數據全部刪掉,然后重新跑數據,這樣其實工作量也比較大,需要補數據,重跑ETL。
另一種方法就是把重復的數據刪掉就行,本文就是針對Greenplum分布式數據庫如何進行去重復刪除操作。
對於在PostgreSQL中,唯一確定一行的位置的是用ctid,可以用這個ctid作為一行的唯一標識;在Oracle中,數據表中的一行的唯一標識可以使用ROWID進行標識,這作為這一行的物理地址信息。而在GP中,要唯一的標識出一行表數據,需要使用gp_segment_id加上ctid進行標識。 gp_segment_id代表的是GP的segment的節點標識,每個子庫的標識是唯一的。
因此刪除重復數據的語句可以這么寫:
delete from public.ods_m_monitor_hour where gp_segment_id::varchar(100)||ctid::varchar(100) in
(select t.ctid from
(select gp_segment_id::varchar(100)||ctid::varchar(100) as ctid,mn_code,pollute_code,monitor_time,
row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num
from public.ods_m_monitor_hour ) t
where t.rows_num >=2);
或:
delete from public.ods_m_monitor_hour where (gp_segment_id,ctid) in
(select t.gp_segment_id,t.ctid from
(select gp_segment_id,ctid,mn_code,pollute_code,monitor_time,
row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num
from public.ods_m_monitor_hour ) t
where t.rows_num >=2);
這種語句適合所有的GP表,特別對那種沒有唯一主鍵的數據倉庫的表進行去重很有用。
用第一種方法分析下步驟:
先分析下,第一步:
select gp_segment_id::varchar(100)||ctid::varchar(100) as ctid,mn_code,pollute_code,monitor_time,
row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num
from public.ods_m_monitor_hour
查出來public.ods_m_monitor_hour 表中字段
gp_segment_id::varchar(100)||ctid::varchar(100) as ctid,mn_code,pollute_code,monitor_time
其中mn_code,pollute_code,monitor_time這幾個字段是這個表中能夠保證唯一性的字段,也就是這幾個字段的值的任一某個組合在這張表只能出現一次,只要出現2次以上,就說明
數據重復了。
然后通過row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num對這幾個字段進行分組排序
通過在外層對這個排序字段rows_num進行條件判斷 :where t.rows_num >=2,就能過濾出重復的表數據。
然后再通過外部條件進行篩選,獲取出這部分重復數據的行數據唯一標識:
delete from public.ods_m_monitor_hour where gp_segment_id::varchar(100)||ctid::varchar(100) in
(select t.ctid from ……)就可以去重重復。
另外,如果表中有唯一標識行的pkid,也就是說有主鍵ID的話,那直接用PKID作為去重字段:
delete from public.ods_m_monitor_hour where pkid in
(select pkid from
(select pkid,mn_code,pollute_code,monitor_time,
row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num
from public.ods_m_monitor_hour ) t
where t.rows_num >=2);
postgresql中去重:
delete from public.ods_m_monitor_hour where ctid in
(select ctid from
(select ctid,mn_code,pollute_code,monitor_time,
row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num
from public.ods_m_monitor_hour ) t
where t.rows_num >=2);
另外:
oracle中去重:
delete from public.ods_m_monitor_hour where ROWID in
(select ROWID from
(select ROWID,mn_code,pollute_code,monitor_time,
row_number() over (partition by mn_code,pollute_code,monitor_time) rows_num
from public.ods_m_monitor_hour ) t
where t.rows_num >=2);