Oracle SQL查询:从表中删除最旧的重复记录

时间:2016-08-17 06:54:15

标签: sql oracle

当前表:

Users:
ID | name|Time        |
001| John|Aug 15      | 
001| Coga|March 1     |
002| Pat |May 10      |

我需要编写一个查询,找到具有相同ID的人并删除最旧的记录。

我能够找到最旧的记录,但如何在同一查询中删除它呢?

SELECT ID, MIN(Time)
FROM Users
WHERE ID in (SELECT ID FROM USERS group by ID having count(ID) > 1)
group by ID;

Result :
ID | Name | Time   |
001| Coga | March 1|

删除时我需要删除具有特定ID和特定时间的确切(最旧)记录。

3 个答案:

答案 0 :(得分:1)

您可以使用此查询:

delete
from   users
where  (id, time) in 
       (select id, time
        from   (select id, time, 
                       row_number() over (partition by id order by time desc) as rn,
                from   users) sub
        where   rn > 1)

它将删除某个人的所有“重复”,但最新的除外。我们的想法是,当您对某个ID的出现次数进行编号时,从最近到旧,只应保留编号为1的记录。

伪列ROWID

正如下面评论中提到的guigui42,Oracle specific pseudo-column rowid可能会进一步提升绩效。如果您没有以id, time字段开头的索引,那肯定会出现这种情况:

delete
from   users
where  rowid in 
       (select rowid
        from   (select rowid, 
                       row_number() over (partition by id order by time desc) as rn,
                from   users) sub
        where   rn > 1)

答案 1 :(得分:0)

尝试使用Windows函数:

ROW_NUMBER会帮助您在ID之前找到第一个(如果IDTIME有重复项,我们只选择其中一个)
COUNT(*) OVER (PARTITION BY)将通过ID

验证是否存在重复项
DELETE USERS
WHERE EXISTS 
   (SELECT 1 
      FROM 
      (SELECT ID, TIME, 
              ROW_NUMBER() OVER (PARTITION BY ID ORDER BY TIME) AS RN,
              COUNT(*) OVER (PARTITION BY ID) CN
         FROM USERS) U
      WHERE U.ID = USERS.ID
        AND U.TIME = USERS.TIME
        AND U.RN = 1 -- FIRST ONE WITH THAT ID
        AND U.CN > 1 -- WE HAVE MORE THAN ONE
       )

答案 2 :(得分:0)

delete 
from 
    USERS 
where
    U_TIME in (select 
                   U_TIME 
               from
                   (select 
                        U_ID,min(U_TIME) as U_TIME,count(rownum) as CNT
                    from 
                        USERS
                    group by 
                        U_ID)
                where 
                    CNT>1 )
;

如果您有任何主键约束,请告诉我