如何删除 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';
我不是 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';