Oracle объединить для, когда совпадение обновления, а затем удалить удаляет все строки - PullRequest
0 голосов
/ 08 февраля 2019

Ниже приведены данные, которые у меня есть.Мне нужно удалить повторяющуюся строку, но параллельно обновлять идентификатор последнего обновления и отметку времени последнего обновления.

Ниже приведены еще 3 столбца, например «Основной ключ», который является уникальным, и отметка времени последнего обновления и идентификатор последнего обновления пользователя.

enter image description here

При выполнении запроса ниже удаляются все 8 строк вместо 4. Я не могу определить, что не так в запросе,

merge into TestTable tgt
using (select ID,
              Date,AMT,
              Currency,
              Value,
              count(*) over (partition by ID, Date, AMT,Currency,Value ) grp_count,
              row_number() over (partition by ID, Date, AMT,Currency,Value order by ID) rn
     from TestTable 
)src
--      where rn > 1) src
on (tgt.ID = src.ID  and src.rn = 2) 
when matched then
    update set  tgt.LastUpdtUser= 'testing',tgt.LastUpdateTime = SYSDATE
    where src.rn = 2
    delete where src.rn = 2;    

Может кто-нибудь, пожалуйста, совет.Мне просто нужно удалить 4 строки с RN = 2, а строка с RN = 1 должна иметь обновленную метку времени.

Также в реальной базе данных также есть много не повторяющихся записей.Мы не хотим что-либо делать в этих.

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Вот альтернативный способ:

delete from testtable 
where rowid in (    
    SELECT rowid FROM testtable a
WHERE rowid > ANY
(SELECT rowid FROM testtable b
WHERE a.id = b.id
));

Это удалит все повторяющиеся строки.Затем вы можете обновить то, что осталось с последним пользователем обновления и временем последнего обновления.

Дайте мне знать, если это сработает лучше для вас.

0 голосов
/ 08 февраля 2019

Похоже, вы пытаетесь удалить дублирующиеся строки, обновляя оставшуюся строку.

Вот как я это сделаю:

MERGE INTO testtable tgt
  USING (SELECT ROWID r_id,
                ID,
                dt,
                amt,
                currency,
                VALUE,
                COUNT(*) OVER (PARTITION BY ID, dt, amt, currency, VALUE) grp_count,
                row_number() OVER (PARTITION BY ID, dt, amt, currency, VALUE ORDER BY lastupdttime) rn
         FROM   testtable) src
  ON (tgt.rowid = src.r_id and src.grp_count > 1)
WHEN MATCHED THEN
  UPDATE SET tgt.lastupdtuser = 'z',
             tgt.lastupdttime = SYSDATE
  DELETE WHERE src.rn > 1;

Чтобы удалить строки с помощьюслияние, вы должны обновить их в первую очередь.Мой оператор слияния получает все строки, которые имеют более 1 строки в группе, и обновляет все строки перед удалением тех, которые не являются первой строкой.

Я изменил порядок в функции row_number () наиспользуйте lastupdttime (потому что таким образом порядок одинаков при каждом запуске оператора, хотя в конечном итоге это не имеет значения), и я также присоединяюсь к rowid каждой строки, так как это простой способ определитьстрока в отсутствие полезного первичного или уникального ключа.Вы можете обновить соединение так, чтобы оно было на первичном / уникальном ключе, если он есть.

0 голосов
/ 08 февраля 2019

Исходя из того, что вы спрашиваете

Выглядит так, как будто вы хотите удалить идентичные записи, имеющие (ID, Дата, AMT, Валюта, Значение)

Если это так, вы можете использоватьудаления дубликата следующим образом

delete
from TestTable a
where a.rowid in 
(
    select b.rowid
    from 
    (
        select row_number() over (partition by ID, Date1, AMT,Currency1,Value
                                  order by ID) rn,
        rowid
        from TestTable  
    )b
    where b.rn<>1  
)

Вот ссылка dbfiddle с полным примером.

https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=572c0aab871a6d1f9c65c4f67da16099

...