如何在 Oracle 中查找并删除表中的重复记录?
问题陈述
您想在 Oracle 中查找并删除表中的重复记录。
解决方案:我们可以使用 Oracle 的内部 ROWID 值来唯一标识表中的行。实现此目的的示例语法如下所示。
delete from table where rowid in (... query here ...)
为了演示用法,我们将首先创建示例数据。
示例
-- table with tennis player rankings DROP TABLE atp_stats; CREATE TABLE atp_stats ( player_rank NUMBER NOT NULL, player_name VARCHAR2(100) NOT NULL, time_range TIMESTAMP(6)); -- sample records INSERT INTO atp_stats VALUES (1,'ROGER FEDERER',CURRENT_TIMESTAMP); INSERT INTO atp_stats VALUES (2,'RAFAEL NADAL',CURRENT_TIMESTAMP); INSERT INTO atp_stats VALUES (3,'NOVAK DJOKOVIC',CURRENT_TIMESTAMP); INSERT INTO atp_stats VALUES (4,'ANDY MURRAY',CURRENT_TIMESTAMP); INSERT INTO atp_stats VALUES (1,'ROGER FEDERER',CURRENT_TIMESTAMP); INSERT INTO atp_stats VALUES (2,'RAFAEL NADAL',CURRENT_TIMESTAMP); INSERT INTO atp_stats VALUES (3,'NOVAK DJOKOVIC',CURRENT_TIMESTAMP); COMMIT;
查看我们刚刚创建的数据。
示例
SELECT * FROM atp_stats ORDER BY 2;
| 球员排名 | 球员姓名 |
| 4 | ANDY MURRAY |
| 3 | NOVAK DJOKOVIC |
| 3 | NOVAK DJOKOVIC |
| 2 | RAFAEL NADAL |
| 2 | RAFAEL NADAL |
| 1 | ROGER FEDERER |
| 1 | ROGER FEDERER |
因此,我们插入了 3 个我们想要删除的重复项。在我们继续编写 Delete 语句之前,让我们了解一下带有 ROWID 的内部查询。
示例
SELECT rowid FROM ( SELECT player_rank, player_rank, rowid , row_number() over (partition BY player_rank, player_name order by player_rank,player_name) AS rnk FROM atp_stats ) WHERE rnk > 1;
我故意将列 player_rank 和 player_name 添加到这个最里面的子查询中,以使逻辑易于理解。理想情况下,最里面的子查询可以不包含它们,效果相同。如果我们只执行这个最里面的查询(当然,为了清楚起见,还选择了额外的列),我们会看到这些结果。
| 球员排名 | 球员姓名 | rowid | rnk |
| 4 | ANDY MURRAY | AAAPHcAAAAAB/4TAAD | 1 |
| 3 | NOVAK DJOKOVIC | AAAPHcAAAAAB/4TAAC | 1 |
| 3 | NOVAK DJOKOVIC | AAAPHcAAAAAB/4TAAG | 2 |
| 2 | RAFAEL NADAL | AAAPHcAAAAAB/4TAAB | 1 |
| 2 | RAFAEL NADAL | AAAPHcAAAAAB/4TAAF | 2 |
| 1 | ROGER FEDERER | AAAPHcAAAAAB/4TAAE | 1 |
| 1 | ROGER FEDERER | AAAPHcAAAAAB/4TAAA | 2 |
SQL 返回表中所有行的 rowid。然后,ROW_NUMBER() 函数在由 PARTITION BY 指令驱动的 id 和 player_name 集上运行。这意味着对于每个唯一的 player_rank 和 player_name,ROW_NUMBER 将开始对我们已将其别名为 rnk 的行的运行计数。当观察到新的 player_rank 和 player_name 组合时,rnk 计数器将重置为 1。
现在,我们可以应用 DELETE 运算符来删除重复值,如下所示。
SQL:删除重复项
示例
DELETE FROM atp_stats WHERE rowid IN ( SELECT rowid FROM( SELECT player_rank, player_name, rowid , row_number() over (partition BY player_rank, player_name order by player_rank,player_name) AS rnk FROM atp_stats ) WHERE rnk > 1 );
输出
3 rows deleted.
| 球员排名 | 球员姓名 |
| 4 | ANDY MURRAY |
| 3 | NOVAK DJOKOVIC |
| 2 | RAFAEL NADAL |
| 1 | ROGER FEDERER |
数据结构
网络
关系数据库管理系统
操作系统
Java
iOS
HTML
CSS
Android
Python
C 编程
C++
C#
MongoDB
MySQL
Javascript
PHP