Oracle清理重复记录

时间:2015-11-25 16:27:16

标签: oracle

我们有一个“文档存档”存储表,如下所示:

FD_RID   KEYWORD  VALUE                    INSUSER  INSDATE
93771    CRID     892448                   CC3      10/25/2005 3:47:09 PM
93771    CRID     892448                   CC3      11/1/2005 12:08:23 PM
93771    DATE     20060101                 CC3      10/25/2005 3:47:09 PM
93771    DATE     20060101                 CC3      11/1/2005 12:08:23 PM
93771    DIST     INT                      AHZ      11/2/2007 11:32:24 AM
93771    DNAME    CDues Inv                CC3      10/25/2005 3:47:09 PM
93771    DNAME    CDues Inv                CC3      11/1/2005 12:08:23 PM
93771    FNAME    \892448\CDues\2006CDues  CC3      10/21/2005 5:11:43 PM
93771    RDATE    20051021                 CC3      10/25/2005 3:47:09 PM
93771    RDATE    20051021                 CC3      11/1/2005 12:08:23 PM

这是一份单一文件的“记录”。可以把它想象成一种元组表,我们有多个由KEYWORD定义的“列”。文档可能具有比上面更多,更少甚至不同的KEYWORD。 我们在表中有30,000,000条记录,其中有数千条记录,其中我们有重复的条目,如上面的条目,CRID,DNAME,RDATE。行也可以有不同的VALUE,只重复KEYWORD。

我需要删除具有重复关键字的最旧的INSDATE记录。我有下面的代码删除所有duplcate行但我不确定它是否会删除记录,如果它有不同的值或它将删除最旧的2个重复。

DELETE FROM fkp_archive WHERE rowid IN (
    SELECT MYROWID FROM (
        SELECT rowid MYROWID, ROW_NUMBER() OVER(PARTITION BY FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER 
                                                    ORDER BY FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER, 
                                                             FKP_INSDATE DESC) RN
        FROM fkp_archive
    ) WHERE RN > 1
)

有没有办法改进上面的代码,以便我可以通过传入我要清理的KEYWORD删除duplcates?

2 个答案:

答案 0 :(得分:0)

对抗重复的第一件事是定义您的(缺少的)主键

这可能是

FKP_FD_RID, FKP_KEYWORD,FKP_VALUE,FKP_INSUSER

如果您容忍不同作者存储的同一关键字中的重复值。

如果要为KEYWORD和RID强制使用唯一值,则只能

FKP_FD_RID, FKP_KEYWORD

另外,我使用4列PK,但请重新检查要求。 在下面的GROUP BY / PARTITION BY子句中使用此列列表

下一步是检查重复

select FKP_FD_RID, FKP_KEYWORD,FKP_VALUE,FKP_INSUSER, count(*) -1 dup_cnt
from fkp_archive
group by FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER
having count(*) > 1
order by 5 desc;

FKP_FD_RID FKP_KEYWORD  FKP_VALUE   USER CNT
93771        CRID           892448      CC3 1
93771        DATE           20060101      CC3   1
93771        RDATE        20051021    CC3   1
93771        DNAME         CDues Inv    CC3 1

最后一列的总和给出了重复的总数 - 即你要摆脱的记录。

根据总计数,您可以决定按照其他答案(CTAS)中的建议重新组织表格。如果这不是一个选项, 你可以逐步删除重复。

这是一个清理前两个关键字的示例,通过限制子查询来简单。 使用上一个查询来获取将要处理的记录数。您也可以仅使用子查询来获得运行删除所需时间的印象。

DELETE FROM fkp_archive WHERE rowid IN (
    SELECT MYROWID FROM (
        SELECT rowid MYROWID, ROW_NUMBER() OVER(PARTITION BY FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER 
                                                    ORDER BY FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER, 
                                                             FKP_INSDATE DESC) RN
        FROM fkp_archive
        where FKP_FD_RID = 93771 and FKP_KEYWORD in ('CRID','DNAME')  /* Limit the scope here */
    ) WHERE RN > 1
)
;

这将删除前两个重复,调整查询以删除其余的。

答案 1 :(得分:0)

如果您按键字段进行分区,那么您的订单将只是您用来确定“较旧”记录的日期字段:

DELETE FROM fkp_archive WHERE rowid IN (
    SELECT MYROWID FROM (
        SELECT rowid MYROWID, ROW_NUMBER() OVER(PARTITION BY FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER 
                                                    ORDER BY FKP_INSDATE DESC) RN
        FROM fkp_archive
    ) WHERE RN > 1
)

那就是说,如果你有3000万行,并且有很多重复,那么我可能会做一个CTAS去除重复。大多数删除,特别是在维护索引时,在大多数情况下会很痛苦(并且很慢)。您还需要担心快照太旧问题,具体取决于需要多长时间。

尝试类似:

-- create new table (CTAS)
create table fkp_archive2 
tablespace mytablespace
-- other storage info here

as
SELECT * FROM fkp_archive WHERE rowid IN (
    SELECT MYROWID FROM (
        SELECT rowid MYROWID, ROW_NUMBER() OVER(PARTITION BY FKP_FD_RID, FKP_KEYWORD, FKP_VALUE, FKP_INSUSER 
                                                    ORDER BY FKP_INSDATE DESC) RN
        FROM fkp_archive
    ) WHERE RN = 1
);
-- TEST new fkp_archive2 to be sure its what you want!
--
-- add back any default column values to fkp_archive2
--
-- DO FOLLOWING IN MAINTENANCE WINDOW
-- drop existing fkp_archive, rename fkp_archive2 -> fkp_archive
-- add indexes/grants/synonyms/etc, generate stats...