Oracle在比赛更新时合并到for中,然后删除将删除所有行

时间:2019-02-08 08:32:19

标签: sql oracle merge

下面是我的数据。我需要删除重复的行,但同时更新上次更新的用户ID和上次更新的时间戳。

下面还有3列,例如“唯一密钥”,“唯一密钥”,“最后更新时间戳记”和“最后更新用户ID”。

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;    

任何人都可以请教。我只需要删除RN = 2的4行,而RN = 1的行应该具有更新的时间戳。

在真实数据库中,也有许多非重复记录。我们不想在那做任何事情。

3 个答案:

答案 0 :(得分:1)

根据您的要求

似乎您要删除具有(ID,Date,AMT,Currency,Value)的相同条目

如果是这样,您可以按照以下方式使用删除重复项

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

答案 1 :(得分:0)

这是另一种方法:

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

这将删除所有重复的行。然后,您可以更新最后更新用户和最后更新时间剩下的内容。

让我知道这是否对您更好。

答案 2 :(得分:0)

您似乎在尝试删除重复的行,同时更新剩余的行。

这就是我要做的:

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;

要通过合并删除行,必须先对其进行更新。我的merge语句获取组中具有多于一行的所有行,并在删除不是第一行的所有行之前更新所有行。

我在row_number()函数中通过使用lastupdttime更改了顺序(因为这样,每次运行该语句的顺序是相同的,尽管最终并不重要),我也加入了每行的rowid,因为这是在没有有用的主键或唯一键的情况下标识行的一种简便方法。如果存在,则可以将连接更新为主键/唯一键。