Суммируйте сумму и затем удаляйте вторую строку при ее дублировании в Oracle - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь сделать ниже две вещи для этой таблицы.

enter image description here

  1. Есть 3 уникальных строки, если мы проверимпо EMP_Id, год и тип.Мне нужно добавить сумму Bonus_Amt только тогда, когда она дублируется.Например, для EMP_ID = 1708301 Bonus_AMT должно быть = 22196 + 3036. Он не должен ничего делать для EMP_ID = 642416.

  2. Как только сумма будет завершена, удалите вторую строку, но тщательно проверьтечто Bonus_Amt должен быть меньше, чем другой в повторяющейся записи.

Запись таблицы должна быть такой же, как показано ниже при выполнении шага 1 и шага 2.

enter image description here

Я попробовал что-то подобное ниже для пункта 1, но это дает мне номер строки 2, а не номер строки 1. Если я изменяю t.rn = 1, то он выбирает все записи, дажетот, который не является дубликатом.

SELECT t.*
FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY o.EMP_Id ORDER BY o.Year) rn
     FROM Emp_Stat o where o.Year='2018' AND o.Type= 'Check' 
     ) t 
WHERE t.rn  > 1 

Здесь UniqueId не имеет значения.Суть в том, что только запись, которая является дубликатом, должна быть суммой, а затем ту, которая не добавлена, должна быть удалена.Также есть столбец lst_update_time, который должен обновляться до sysdate только для повторяющейся строки, а не для любой другой записи.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Мне нравится ответ с оператором слияния;Просто хотел предложить более прозрачное решение:

  1. Start
  2. Выберите сумму, сгруппированную по Великобритании (как в этом операторе слияния) и вставьте результаты во вспомогательную таблицу.- У вас будет одна запись на одну Великобританию
  3. Удалить ВСЕ записи из базовой таблицы
  4. Вставить в базовую таблицу из вспомогательной таблицы
  5. совершить работу;
0 голосов
/ 21 ноября 2018

Вы можете сделать это в одном операторе 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 каждой строки (вам нужно обновить каждую строку, иначе удаление не будет «видеть»необновленные строки) перед удалением всех, кроме первой строки в каждой группе.

...