Oracle 删除重复数据只留一条

本文介绍如何使用SQL查询和删除数据库表中的重复记录,包括基于单个字段和多个字段的重复记录处理方法,并提供了具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

查询及删除重复记录的SQL语句

1、查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断 
select * from 表 
where Id in (select Id from 表 group byId having count(Id) > 1)
 
2、删除表中多余的重复记录,重复记录是根据单个字段(Id)来判断,只留有rowid最小的记录 
DELETE from 表 WHERE id IN ( SELECT id FROM 表 GROUP BY id HAVING COUNT(id) > 1) 
                     AND ROWID NOT IN (SELECT MIN(ROWID) FROM 表 GROUP BY id HAVING COUNT(*) > 1);
 
3、查找表中多余的重复记录(多个字段) 
select * from 表 a where (a.Id,a.seq) in(select Id,seq from 表 group by Id,seq having count(*) > 1)
 
4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录
delete from 表 a 
where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) 
      and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)
 
5、查找表中多余的重复记录(多个字段),不包含rowid最小的记录
 select * from 表 a 
where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) 
and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)

如下例子
--单个字段
create table Student(
ID NUMBER(8) PRIMARY KEY,
NAME VARCHAR(50));

INSERT INTO Student (ID,NAME) VALUES(100001,'Zhang San');
INSERT INTO Student (ID,NAME) VALUES(100002,'Li Si');
INSERT INTO Student (ID,NAME) VALUES(100003,'Zhang San');
INSERT INTO Student (ID,NAME) VALUES(100004,'Wang Wu');
INSERT INTO Student (ID,NAME) VALUES(100005,'Li Si');

select * from Student;

select rowid,stu.* from Student stu where stu.name in(select name from Student group by name having count(name)>1);

delete from Student where name in(select name from Student group by name having count(name)>1)
and ROWID NOT IN(SELECT MIN(ROWID)FROM Student group by name  having count(name)>1);

--两个字段
create table Student_Subject(
STU_ID NUMBER(8) NOT NULL,
SUB_ID NUMBER(8) NOT NULL);


INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10001,10);
INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10002,10);
INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10001,10);
INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10001,11);
INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10001,12);
INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10002,10);
INSERT INTO Student_Subject (STU_ID,SUB_ID) VALUES(10002,11);


SELECT * FROM Student_Subject order by STU_ID,SUB_ID;


--查找表中多余的重复记录(两个字段)
SELECT ROWID,ss.*
FROM Student_Subject ss
where (ss.STU_ID,ss.SUB_ID) in
         (select STU_ID,SUB_ID from Student_Subject group by STU_ID,SUB_ID having count(*)>1);


--查找表中多余的重复记录(两个字段),不包含rowid最小的记录
SELECT ROWID,ss.*
FROM Student_Subject ss
WHERE (ss.STU_ID,ss.SUB_ID)in (select STU_ID,SUB_ID
                               from Student_Subject
                               group by STU_ID,SUB_ID
                               having count(*)>1)
      and ROWID NOT IN(select min(ROWID) from Student_Subject group by STU_ID,SUB_ID having count(*)>1)
ORDER BY ss.STU_ID,ss.SUB_ID;


--删除表中多余的重复记录(两个字段),只留有rowid最小的记录
DELETE FROM Student_Subject
WHERE (STU_ID,SUB_ID) in (select STU_ID,SUB_ID
                         from Student_Subject
                         group by STU_ID,SUB_ID
                         having count(*)>1)
      and ROWID NOT IN (select min(ROWID) from Student_Subject group by STU_ID,SUB_ID having count(*)>1);
### Oracle 删除重复数据仅保一条的SQL方法 在Oracle数据库中,可以通过`ROWID`来唯一标识每一行数据,并利用分组查询和子查询的方式删除重复记录。以下是几种常见的解决方案: #### 方法一:基于 `ROWID` 和 `GROUP BY` 此方法适用于判断重复的标准为多个字段的情况。 ```sql DELETE FROM your_table WHERE ROWID NOT IN ( SELECT MIN(ROWID) FROM your_table GROUP BY column1, column2, ..., columnN ); ``` 这种方法通过 `MIN(ROWID)` 获取每组中的最小 `ROWID` 值,从而保该行并删除其他重复行[^1]。 --- #### 方法二:基于窗口函数 `ROW_NUMBER()` 如果需要按照某个特定顺序(如时间戳或日期字段)保最新的记录,可以使用窗口函数 `ROW_NUMBER()`。 ```sql DELETE FROM your_table WHERE id IN ( SELECT id FROM ( SELECT t.*, ROW_NUMBER() OVER (PARTITION BY column1, column2, ..., columnN ORDER BY date_column DESC) AS rn FROM your_table t ) WHERE rn != 1 ); ``` 在此方案中,`ROW_NUMBER()` 函数会对指定列组合进行分区,并按给定的排序规则分配序号。最终删除所有序号不等于1的行[^3]。 --- #### 方法三:针对单个字段作为重复标准 当只需要依据单一字段判断是否重复时,可采用如下方式: ```sql DELETE FROM your_table a WHERE EXISTS ( SELECT 1 FROM your_table b WHERE a.column_name = b.column_name AND a.ROWID > b.ROWID ); ``` 这里通过比较两行之间的 `ROWID` 大小,确保每次只保具有较小 `ROWID` 的那记录[^5]。 --- #### 注意事项 - 如果尝试直接操作带有大量数据的大表,建议先创建临时表存储中间结果再执行删除动作,以免影响性能。 - 使用上述语句之前最好备份原始表格以防误删重要资料。 问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值