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

问题描述

我不是数据库方面的专家,我正在处理此查询删除重复项。

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

enter image description here

我想要这样的结果

enter image description here

就像我应该有一个唯一的条目,其中代码、单位和类型为 ACTIVE 状态。 所以第 1、2、3、7、8 行对我来说是重复的,我需要在最大validity_until 的情况下保留 1 个条目。需要为需要删除的条目获取 EventId 以从其他表中删除链接对象。 我可以通过查询检索重复项

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

但是如何根据 max(validity_until) 从这些重复记录中检索 event_id。 一旦我有像 aaa、ccc 这样的 Event_id 被删除并需要保留 hhh,我就可以删除第 11 行的事件 aaa 的历史记录。但我想保留第 7 行,这是 ggg 事件,它的历史记录完好无损,这是第 6 行。 并且需要从该事件表中删除标识符为Event_id的Solution表中对应的重复记录。

输入:

行号 Event_Id 代码 单位 类型 validity_until 状态
1 aaa 111 1 A 12-JAN-21 12.01.01.625000 PM 活跃
2 bbb 222 2 B 02-JAN-21 12.01.01.625000 PM 活跃
3 抄送 111 1 A 15-JAN-21 12.01.01.625000 PM 活跃
4 ddd 333 2 C 12-JAN-21 12.01.01.625000 PM 活跃
5 ee 222 3 A 11-JAN-21 12.01.01.625000 PM 活跃
6 ggg 222 2 B 05-JAN-21 12.01.01.625000 PM 无效
7 ggg 222 2 B 12-JAN-21 12.01.01.625000 PM 活跃
8 呵呵 111 1 A 20-JAN-21 12.01.01.625000 PM 活跃
9 ddd 333 2 C 10-JAN-21 12.01.01.625000 PM 无效
10 ee 222 3 A 01-JAN-21 12.01.01.625000 PM 无效
11 aaa 111 1 A 13-JAN-21 12.01.01.625000 PM 无效

预期结果:

行号 Event_Id 代码 单位 类型 validity_until 状态
4 ddd 333 2 C 12-JAN-21 12.01.01.625000 PM 活跃
5 ee 222 3 A 11-JAN-21 12.01.01.625000 PM 活跃
6 ggg 222 2 B 05-JAN-21 12.01.01.625000 PM 无效
7 ggg 222 2 B 12-JAN-21 12.01.01.625000 PM 活跃
8 呵呵 111 1 A 20-JAN-21 12.01.01.625000 PM 活跃
9 ddd 333 2 C 10-JAN-21 12.01.01.625000 PM 无效
10 ee 222 3 A 01-JAN-21 12.01.01.625000 PM 无效

解决方法

使用 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,Status FROM event  
)
SELECT * FROM RESULTS WHERE RN=1 OR STATUS='INACTIVE';