删除Oracle SQL中的重复行,保留最新条目

删除Oracle SQL中的重复行,保留最新条目,sql,oracle,duplicates,sql-delete,Sql,Oracle,Duplicates,Sql Delete,我使用下面的SQL来识别“transaction_list”表中的重复项。这很好用。现在,我想根据这些条件删除该表中的所有重复项,只保留最新的条目。这些可以通过“上次更新”列来识别。我尝试了不同的DELETE语句,但没有成功。非常感谢您的任何建议 SELECT par_num ,tran_num ,COUNT(*) AS num_duplicates FROM transaction_list WHERE last_update >= to_date('01-mar-2020 00:00:

我使用下面的SQL来识别“transaction_list”表中的重复项。这很好用。现在,我想根据这些条件删除该表中的所有重复项,只保留最新的条目。这些可以通过“上次更新”列来识别。我尝试了不同的DELETE语句,但没有成功。非常感谢您的任何建议

SELECT par_num
,tran_num
,COUNT(*) AS num_duplicates
FROM transaction_list
WHERE last_update >= to_date('01-mar-2020 00:00:00', 'dd-mon-yyyy 
hh24:mi:ss')
GROUP BY par_num
,tran_num
HAVING COUNT(*) > 1
ORDER BY par_num

以下是一种使用行ID的方法:

delete from transaction
where 
    last_update = date '2020-03-01'
    and rowid in (
        select rid
        from (
            select 
                rowid rid, 
                row_number() over(partition by par_num ,tran_num order by last_update desc) rn
            from transaction                
        ) t
        where rn > 1
    )

子查询为组中不是最新的行(即所有记录具有相同的
par\u num,tran\u num
)生成行ID列表-使用
row\u number()
标识每个组的最新记录。外部查询只删除这些行。

如果想法是删除所有
par_num
/
tran_num
重复项,但
last_update
排序的每个集合中的最后一个除外,那么应该这样做:

delete transaction_list
where  rowid in
       ( select lag(rowid)
                over (partition by par_num, tran_num order by last_update)
         from   transaction_list );


说明:返回上一行的值(或另一行-如果需要,可以指定所有类型的偏移逻辑,但这里我们只需要上一行)。该子句指定了排序和窗口设置。在这种情况下,我们希望通过
last\u update
对每组
par\u num
/
tran\u num
组合进行排序,并删除前一行。
partitionby
部分意味着为每个
par_num
/
tran_num
组合重置排序,因此每个组都有一个不会被删除的“最后”行。

谢谢,但它抛出错误:ORA-00904:“RN”:无效identifier@Skywalker:对不起,我忘了给
行编号()
一个别名。修正了。3月1日在您的示例代码中的意义是什么?您是特别想要那个日期和时间,还是在决定删除哪个
par_num/tran_num
副本时,您只是想用
last_update
作为分界线?谢谢。非常有用。你能解释一下滞后(rowid)和按功划分的情况吗?我对他们不熟悉。补充说明。谢谢,伙计,非常感谢!非常清楚和简洁。要完全理解,ORDER BY的目的是什么,这是唯一可选的吗?
lag
函数需要进行排序,以便知道哪一行是前一行。(再次看了看我的答案,我意识到我把
par_num
tran_num
放在了
order by
子句中不需要它们的地方。希望没有它们会更清楚。)谢谢你,威廉!希望这里的所有人都像你一样解释:-)