以正确的方式在多个列的大表中查找重复记录

时间:2014-10-06 16:19:24

标签: sql postgresql postgresql-8.4

我现在已经阅读了很多关于这个主题的主题,并尝试了一些方法,但它没有像我希望的那样工作。如果这被认为是一个重复的话题,我需要澄清并道歉。

我的一个客户端拥有一个Postgres数据库,其中一个表包含超过1200万条记录。他们让我找到重复的记录,提取它们以供查看,如果一切正常,删除重复记录。

我主要担心的是服务器上的性能。在1200万条记录上运行DISTINCT查询必须消耗大量资源吗?

由于我的第一个任务是提取要查看的记录,比如CSV,而不是简单地删除它们,我在PgAdmin中的方法是将其执行到文件中。

SELECT * 
FROM
    my_table
WHERE
my_table_id NOT IN (

                SELECT DISTINCT 
                    ON (
                        num_1,
                        num_2,
                        num_3,
                        num_4,
                        num_5,
                        my_date
                    )
                    my_table_id
                FROM
                    my_table
);

然而,这个查询需要很长时间。执行20分钟后,我停止了执行。为了使事情变得更复杂,我的客户端不愿意允许我克隆表的本地副本,因为它具有严格的安全性。他们更喜欢这一切都是在现场托管环境中完成的。

表定义非常简单。看起来像这样

CREATE TABLE my_table
(
    my_table_id bigserial NOT NULL,
    num_1 bigserial NOT NULL,
    num_2 bigserial NOT NULL,
    num_3 bigserial NOT NULL,
    num_4 numeric,
    num_5 integer,
    my_date date,
    my_text character varying
)

主键“my_table_id”尚未受到损害,并且始终是唯一的。 col“my_text”在查询中没有意义,因为它对于所有重复项都是空的。它只是数字字段和需要匹配的日期。所有列(my_table_id和my_text除外)必须匹配跨记录才有资格作为重复。

解决此问题的最佳方法是什么?是否有一种服务器友好的方式不会占用主机环境中的所有资源?请帮助我了解最佳方法!

谢谢!

2 个答案:

答案 0 :(得分:4)

使用分析函数的另一种方法

select * from (
    select * , 
    count(*) over (partition by num1,num2,num3,num4,my_date) cnt
    from mytable
) t1 where cnt > 1

答案 1 :(得分:3)

需要使用GROUP BYHAVING来获取重复记录,而不是DISTINCT

子查询将找到所有重复记录

SELECT * FROM
my_table mt
JOIN
(
     SELECT
            num_1,
            num_2,
            num_3,
            num_4,
            num_5,
            my_date
     FROM
            my_table
     GROUP BY num_1, num_2, num_3, num_4, num_5, my_date
     HAVING COUNT(*) >1
) T 
ON mt.num_1= T.num_1
and mt.num_2= T.num_2
and mt.num_3= T.num_3
and mt.num_4= T.num_4
and mt.num_5= T.num_5
and mt.my_date= T.my_date