如何删除 oracle 上的重复项,其中重复条件和标识符列不同,保持最新记录与其之前的更新

How to delete duplicates on oracle where duplicate criteria and identifier columns are different keeping latest record with its previous updates

我不是 DB 专家,我正在处理这个查询以删除重复项。

基本上,我 Table 事件的数据类似于

我想要这样的结果

好像我应该有一个唯一的条目,其中包含代码、单位和类型作为活动状态。 所以第 1、2、3、7、8 行对我来说是重复的,我需要保留 1 个条目不重复,最大值为 validity_until。需要为需要删除的条目获取 EventId,以便从其他 tables 中删除链接对象。 我可以通过查询

检索重复项
SELECT code,unit,type FROM event where status='ACTIVE' GROUP BY code,unit,type having count(*) > 1 ;

然后如何根据 max(validity_until) 从这些重复记录中检索 event_id。 一旦我有 Event_id 像 aaa,ccc 被删除并需要保留 hhh,我将能够删除事件 aaa 的历史记录,即第 11 行。但我想保留第 7 行,即 ggg 事件及其历史记录完好无损,即第 6 行。 并且需要从解决方案 table 中删除相应的重复记录,其中标识符是 Event_id 来自此事件 table.

输入:

Row id Event_Id Code unit type validity_until Status
1 aaa 111 1 A 12-JAN-21 12.01.01.625000 PM ACTIVE
2 bbb 222 2 B 02-JAN-21 12.01.01.625000 PM ACTIVE
3 ccc 111 1 A 15-JAN-21 12.01.01.625000 PM ACTIVE
4 ddd 333 2 C 12-JAN-21 12.01.01.625000 PM ACTIVE
5 eee 222 3 A 11-JAN-21 12.01.01.625000 PM ACTIVE
6 ggg 222 2 B 05-JAN-21 12.01.01.625000 PM INACTIVE
7 ggg 222 2 B 12-JAN-21 12.01.01.625000 PM ACTIVE
8 hhh 111 1 A 20-JAN-21 12.01.01.625000 PM ACTIVE
9 ddd 333 2 C 10-JAN-21 12.01.01.625000 PM INACTIVE
10 eee 222 3 A 01-JAN-21 12.01.01.625000 PM INACTIVE
11 aaa 111 1 A 13-JAN-21 12.01.01.625000 PM INACTIVE

预期结果:

Row id Event_Id Code unit type validity_until Status
4 ddd 333 2 C 12-JAN-21 12.01.01.625000 PM ACTIVE
5 eee 222 3 A 11-JAN-21 12.01.01.625000 PM ACTIVE
6 ggg 222 2 B 05-JAN-21 12.01.01.625000 PM INACTIVE
7 ggg 222 2 B 12-JAN-21 12.01.01.625000 PM ACTIVE
8 hhh 111 1 A 20-JAN-21 12.01.01.625000 PM ACTIVE
9 ddd 333 2 C 10-JAN-21 12.01.01.625000 PM INACTIVE
10 eee 222 3 A 01-JAN-21 12.01.01.625000 PM INACTIVE

使用row_number如下:

Select * from
(Select t.*,
       Row_number() over (partition by Code, Unit, type order by validity_until desc) as rn
  From t) t
Where rn = 1 or status <> 'ACTIVE'

感谢您分享示例数据和输出结果。这是您想要的查询:

WITH RESULTS AS (
SELECT ROW_NUMBER()OVER( PARTITION BY CODE,UNIT,TYPE ORDER BY validity_until DESC) AS RN,row_id ,event_id,  code,   unit,   type,   validity_until, Status FROM event  
)
SELECT * FROM RESULTS WHERE RN=1 OR STATUS='INACTIVE'

如果相同的 代码、单位、类型和 validity_until 不可能出现多行,您可以使用 dense_rank() 而不是 row_number。虽然两者都在某个地方使用分区,但我读到它更快(不确定但你可以试一试):

WITH RESULTS AS (
SELECT dense_rank()OVER( PARTITION BY CODE,UNIT,TYPE ORDER BY validity_until DESC) AS RN,row_id ,event_id,  code,   unit,   type,   validity_until, Status FROM event  
)
SELECT * FROM RESULTS WHERE RN=1 OR STATUS='INACTIVE';