我们有一个“文档存档”存储表,如下所示:
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?
答案 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...