如何删除postgres中的重复项(没有唯一ID)

时间:2017-10-21 05:09:40

标签: postgresql duplicates uniqueidentifier

删除重复行时遇到一些困难。我认为user_id和time_id一起充当标识符,但是那些甚至有重复。

user_id(text),time_id(bigint),value1(数字)

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

在这种情况下,如何删除重复项? 由于我在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)

3 个答案:

答案 0 :(得分:2)

Postgres中的每个表都有一些隐藏的system columns。根据定义,其中一个(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)上创建主键,或者为此创建一个新的唯一列。

答案 1 :(得分:1)

请谨慎使用有关删除的任何建议,请确保您有必要“撤消”删除。我认为你需要添加一个自动编号的列来协助这项工作

alter table tablename add column is_uniq serial

然后我建议使用row_number()来帮助识别你想要保留的行(其中rn = 1)和要删除的行(其中rn> 1)。使用以下指南:

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

我不确定是否有任何其他列用于order by,但如果有,那么你也可以将它包含在over子句中。

一旦你有“is_uniq”列和rn&gt; 1行,你应该可以安全地删除不需要的行。

答案 2 :(得分: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;