Sql Oracle在“匹配更新然后删除”删除所有行时合并到中

Sql Oracle在“匹配更新然后删除”删除所有行时合并到中,sql,oracle,merge,Sql,Oracle,Merge,下面是我掌握的数据。我需要删除重复的行,但同时更新上次更新用户id和上次更新时间戳 下面还有3列,如唯一的主键、上次更新时间戳和上次更新用户Id 当执行下面的查询时,它将删除所有8行而不是4行。 我无法识别查询中的错误 merge into TestTable tgt using (select ID, Date,AMT, Currency, Value, count(*) over

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

下面还有3列,如唯一的主键、上次更新时间戳和上次更新用户Id

当执行下面的查询时,它将删除所有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的行应该有更新的时间戳


在真实数据库中也有许多不重复的记录。我们不想在这些方面做任何事情。

根据您的要求

看起来好像您要删除ID、日期、金额、币种和值相同的条目

如果是这样,您可以按如下方式使用删除副本

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链接和一个完整的示例


以下是另一种方法:

delete from testtable 
where rowid in (    
    SELECT rowid FROM testtable a
WHERE rowid > ANY
(SELECT rowid FROM testtable b
WHERE a.id = b.id
));
这将删除所有重复的行。然后,您可以更新上次更新用户和上次更新时间的剩余内容


让我知道这是否对您更合适。

看起来您正在尝试删除重复的行,同时更新剩余的行

我是这样做的:

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语句获取组中有超过1行的所有行,并在删除任何不是第一行的行之前更新所有行


我将row_number函数中的order by改为使用lastupdtime,因为这样,每次运行语句时的顺序都是相同的,尽管最终这并不重要,我还加入了每行的rowid,因为这是一种在缺少有用主键或唯一键的情况下识别行的简单方法。如果存在主键/唯一键,您可以将联接更新为主键/唯一键。

您的update where子句不应该是where src.rn=1吗?是的,在粘贴到此处时对其进行了修改,但重点是此处没有发生删除。当它只删除4行时,它将删除所有8行。但是tgt.ID=src.ID和src.rn=2将阻止选择rn=1的行,从而成为更新的候选行,否?在合并查询中,它将删除所有内容,因为您指定的条件与tgt.ID=src.ID和src.rn=2上的所有行->匹配。这里您说的是匹配Tgt中的所有记录,其ID与rn=2的src_块匹配。由于您所有的行都有重复的条目,所以对于每个分区子句,总是有一个rn=2的记录