从没有主键的Postgresql表中删除重复记录?

时间:2015-05-11 07:01:37

标签: sql postgresql

我有像

这样的表格
CREATE TABLE meta.fk_payment1
(
  id serial NOT NULL,
  settlement_ref_no character varying,
  order_type character varying,
  fulfilment_type character varying,
  seller_sku character varying,
  wsn character varying,
  order_id character varying,
  order_item_id bigint,
   ....
  );

我从csv文件插入数据,其中所有列都相同而不是 id列

如果csv文件上传的次数超过一次,数据将会重复。

但是id不会,而id是主键。

所以我想在不使用主键的情况下删除所有重复的行。

我必须在单个表

上执行此操作

5 个答案:

答案 0 :(得分:13)

你可以这样做 的 e.g。

DELETE FROM table_name
    WHERE   ctid NOT IN
    (SELECT     MAX(dt.ctid)
        FROM        table_name As dt
        GROUP BY    dt.*);

运行此查询

DELETE FROM meta.fk_payment1
    WHERE   ctid NOT IN
    (SELECT     MAX(dt.ctid)
        FROM        meta.fk_payment1 As dt
        GROUP BY    dt.*);

答案 1 :(得分:2)

将不同数据复制到工作表fk_payment1_copy。最简单的方法是使用into

SELECT max(id),settlement_ref_no ... 
INTO fk_payment1_copy
from fk_payment1
GROUP BY settlement_ref_no ... 

fk_payment1

删除所有行
delete from fk_payment1

并将数据从fk_payment1_copy表格复制到fk_payment1

insert into fk_payment1
select id,settlement_ref_no ... 
from fk_payment1_copy

答案 2 :(得分:1)

对问题中的主要关键部分有点不确定,但无论如何id不需要是主键,它只需要是唯一的。因为它应该是串行的。因此,如果它具有唯一值,您可以这样做:

DELETE FROM fk_payment1 f WHERE EXISTS
  (SELECT * FROM fk_payment1 WHERE id<f.id
   AND settlement_ref_no=f.settlement_ref_no
   AND ...)

只需要在select查询中添加所有列。这样,将删除具有相同值(除了id)并且在此行之后(按id排序)的所有行。

(另外,使用fk_前缀命名表使其看起来像外键。)

答案 3 :(得分:1)

如果表格不是很大,你可以这样做:

-- create temporary table and select distinct into it. 
CREATE TEMP TABLE tmp_table AS 
SELECT DISTINCT column_1, column_2 
FROM original_table ORDER BY column_1, column_2;

-- clear the original table 
TRUNCATE original_table;

-- copy data back in again 
INSERT INTO original_table(column_1, column_2) 
SELECT * FROM  tmp_table ORDER BY column_1, column_2;

-- clean up
DROP TABLE tmp_table
  • 对于较大的表,从tmp_table创建
  • 中删除TEMP命令
  • 这个解决方案在使用JPA(Hibernate)生成的@ElementCollection时非常方便,它是在没有主键的情况下创建的。

答案 4 :(得分:0)

所以PG维基中有一个灵巧的方式。 https://wiki.postgresql.org/wiki/Deleting_duplicates

此查询对具有相同column1,column2和column3的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);

我正在对重复600k行进行测试,导致200k行的独特行。使用group by和NOT IN的解决方案需要3h +,这需要3s。