环境 :
SQL> SELECT * FROM V$VERSION; BANNER ---------------------------------------------------------------- Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product PL/SQL Release 10.2.0.1.0 - Production CORE 10.2.0.1.0 Production TNS for 32-bit Windows: Version 10.2.0.1.0 - Production NLSRTL Version 10.2.0.1.0 - Production
网上有很多的删除重复数据的 SQL 的例子. 有使用 GROUP BY HAVING 等, 还有一个 DISTINCT 关键字,这个可以忽略 .怎么可能会有数据完全相同的记录. 那单条数据怎么定位.难道靠 伪例 ?
CREATE TABLE TEMPTEMP ( ID NUMBER, NAME VARCHAR2(20) ); -- 生成重复数据 -- 0.297秒 DECLARE BEGIN FOR I IN 1..10000 LOOP INSERT INTO TEMPTEMP VALUES (I, 'AAA' || I); END LOOP; END; / -- 0.015 DECLARE BEGIN FOR I IN 1..1000 LOOP INSERT INTO TEMPTEMP VALUES (I, 'AAA' || I); END LOOP; END; / -- 0.031 DECLARE TE INT; BEGIN FOR I IN 10001..11000 LOOP TE := 1; INSERT INTO TEMPTEMP VALUES (I, 'AAA' || TE); TE := TE + 1; END LOOP; END; / SQL> select count(*) from temptemp; COUNT(*) -------------- 12000
建立索引
-- 0.015秒 建索引 CREATE INDEX INDEX_TEMP ON TEMPTEMP(ID, NAME);
我现在假定要将 两列数据相同的记录进行删除, 不考虑主键. 不使用临时表, 不考虑把数据从两个表导来导去
有两条 SQL ,我现在只想要效率 .比较了一下, 后者的效率似乎确实要快
只匹配 NAME 完全相等的记录
-- 0.047秒 2000 rows deleted DELETE FROM TEMPTEMP T1 WHERE T1.ROWID != (SELECT MAX(T2.ROWID) FROM TEMPTEMP T2 WHERE /*T1.ID = T2.ID AND*/ T1.NAME = T2.NAME); -- 去掉 注释后 0.047秒 1000 rows deleted
使用分析函数
-- 0.031秒 2000 rows deleted DELETE FROM TEMPTEMP T1 WHERE T1.ROWID IN (SELECT RID FROM (SELECT ROWID RID, ROW_NUMBER() OVER (PARTITION BY /*ID,*/ NAME ORDER BY ROWID) RN FROM TEMPTEMP) WHERE RN != 1); -- 去掉 ID 匹配后 0.031秒 1000 rows deleted
PS: 不知道是不是数据量太少还是表结构过于简单的原因 , 创了索引后 的效率 并不明显. 所需时间完全一样
Example 中的数据量确实很少. 也临到下班, 没有 过多的再去测试 效率 .若有人有更好效率更高的方法. 请教则个....