上一篇
Oracle中,统计重复数据可通过多种方法,如使用
GROUP BY语句按字段分组并配合
HAVING子句筛选重复记录;利用内连接合并表后查找相同数据;还可借助
ROW_NUMBER() OVER窗口函数为数据分配行号,再筛选出重复数据
Oracle数据库中,统计重复数据是一项常见且重要的任务,尤其在处理大量数据时,以下是几种常用的方法及其详细说明:
使用GROUP BY语句
基本用法
GROUP BY语句是Oracle中统计重复数据的基础方法,通过将数据按指定字段分组,并结合HAVING子句筛选出出现次数大于1的记录,可以有效找出重复数据。- 示例:统计
person表中重复的名字及其出现次数。SELECT name, COUNT() AS 重复次数 FROM person GROUP BY name HAVING COUNT() > 1;
- 说明:此查询将数据按
name字段分组,统计每组的记录数,并通过HAVING子句筛选出重复的记录,适用于非唯一索引字段(如人名、生日等)的重复统计。
多字段分组
- 当需要统计多个字段的组合重复时,可以在
GROUP BY中指定多个字段。 - 示例:统计
cs表中xm(姓名)、zjh(证件号)、dz(地址)三个字段均重复的记录。SELECT xm, zjh, dz, COUNT() AS 重复次数 FROM cs GROUP BY xm, zjh, dz HAVING COUNT() > 1;
- 说明:此查询适用于需要同时匹配多个字段的重复数据场景。
使用ROW_NUMBER() OVER语句
窗口函数的应用
ROW_NUMBER() OVER是Oracle的高级分析函数,通过为每组数据分配行号,可以快速识别重复记录。- 示例:查找
person表中重复的名字,并保留每组中id最小的记录。SELECT name FROM ( SELECT name, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id) AS rn FROM person ) WHERE rn > 1;
- 说明:此查询将数据按
name分组,并为每组数据按id排序后分配行号。rn > 1表示重复记录,适用于多列重复或需要保留特定记录的场景。
结合子查询删除重复数据
- 通过
ROW_NUMBER()可以为每组数据标记唯一编号,进而删除重复记录。 - 示例:删除
cs表中zjh(证件号)重复的记录,仅保留rowid最小的记录。DELETE FROM cs WHERE (xm, zjh, dz) IN ( SELECT xm, zjh, dz FROM cs GROUP BY xm, zjh, dz HAVING COUNT() > 1 ) AND rowid NOT IN ( SELECT MIN(rowid) FROM cs GROUP BY xm, zjh, dz HAVING COUNT() > 1 );
- 说明:此方法通过子查询定位重复记录,并结合
rowid保留唯一记录,适用于多字段去重。
使用自关联查询
基于ROWID的自关联
ROWID是Oracle表的唯一标识符,通过自关联可以快速查找重复数据。- 示例:查询
cs表中xm、zjh、dz均重复的记录。SELECT a. FROM cs a WHERE EXISTS ( SELECT 1 FROM cs b WHERE a.xm = b.xm AND a.zjh = b.zjh AND a.dz = b.dz AND a.rowid != b.rowid ); - 说明:此查询通过自关联比较
ROWID,确保返回的是重复记录,适用于需要精确匹配所有字段的场景。
性能优化技巧
| 方法 | 适用场景 | 优化建议 |
|---|---|---|
| GROUP BY | 单字段或多字段分组统计 | 对分组字段建立索引,避免全表扫描 |
| ROW_NUMBER() OVER | 多列重复或需保留特定记录 | 使用分区索引,减少排序开销 |
| 自关联查询 | 精确匹配所有字段 | 结合ROWID过滤,减少重复比较 |
| 子查询+逻辑条件 | 删除重复记录 | 分批处理大数据,避免锁定全表 |
相关FAQs
如何统计某个字段的重复次数?
使用GROUP BY结合COUNT(),
SELECT field_name, COUNT() AS 重复次数 FROM table_name GROUP BY field_name HAVING COUNT() > 1;
如何删除重复记录并保留一条?
通过ROW_NUMBER()或ROWID结合子查询,
DELETE FROM table_name WHERE rowid NOT IN ( SELECT MIN(rowid) FROM table_name GROUP BY duplicate
