Вы можете сделать это в одном операторе MERGE, используя update и delete в предложении when matched
, например:
merge into t1 tgt
using (select unique_id,
emp_id,
sum(bonus_amt) over (partition by emp_id, year, type) new_bonus_amt,
year,
type,
count(*) over (partition by emp_id, year, type) grp_count,
row_number() over (partition by emp_id, year, type order by bonus_amt desc) rn
from t1) src
on (tgt.unique_id = src.unique_id and src.grp_count > 1)
when matched then
update set tgt.bonus_amt = src.new_bonus_amt,
tgt.last_update_time = sysdate
delete where rn != 1;
Demo DBFiddle
Это работает путем нахождения суммы bonus_amt для каждой группы (не имеет значения, имеет ли группа одну строку или несколько) и идентифицирует первую строку в группе (то есть ту, которая имеет наивысший bonus_amt), поэтому мызнать, какую строку сохранить.
Затем мы используем этот исходный набор данных в операторе слияния для обновления bonus_amt каждой строки (вам нужно обновить каждую строку, иначе удаление не будет «видеть»необновленные строки) перед удалением всех, кроме первой строки в каждой группе.