如果有重复记录,则更新同一表的列

Posted

技术标签:

【中文标题】如果有重复记录,则更新同一表的列【英文标题】:Update a column of same table if there is duplicate records 【发布时间】:2016-04-11 06:34:30 【问题描述】:

如果表中的行重复,我需要更新列。

这里的场景是如果有 3 行重复,那么我们必须将两行标记为错误,将一行标记为成功。

虚拟数据可能是这样的

create table test_dup (acc_num number, tel_num number, imsi number, done varchar2(20));

insert into test_dup values (43532111, 9874554422, 58944235, null);
insert into test_dup values (43532111, 9874554422, 58944235, null);
insert into test_dup values (43532111, 9874554422, 58944235, null);

insert into test_dup values (43532333, 9845781554, 265454522, null);

insert into test_dup values (623352777, 9928123457, 89455422, null);
insert into test_dup values (623352777, 9928123457, 89455422, null);

select acc_num, tel_num, imsi 
  from test_dup  
group by acc_num, tel_num, imsi having count(acc_num) > 1;

这个查询给出了重复的行 但这里的问题是,我需要将 2 行 acc_num 43532111 的 DONE 列更新为“错误”,将 1 行更新为“成功”,因此如果我使用类似 ...

的更新语句
update test_dup
  set done = 'error'
where (acc_num,tel_num, imsi) in (select acc_num, tel_num, imsi
                                 from test_dup
                            group by acc_num, tel_num, imsi
                            having count(acc_num) > 1);

然后它更新 5 行,即除非重复行之外的所有重复行。

但在我们的例子中,它应该只更新 3 行 2 个重复的 acc_num = 43532111 和 1 个重复的 acc_num = 623352777 为“错误”

真实的表大约有35列,那么有什么方法可以不用为group by子句写下每一列的名称?

我正在使用---

Oracle Database 12c 企业版版本 12.1.0.2.0 - 64 位生产

请不要尝试拨打以上号码,它们仅用于测试目的!

【问题讨论】:

最简单的解决方案是实现主键以防止插入重复行。我不知道 Oracle 是否支持在所有 35 列上使用 ROW_NUMBER 从 cte 进行 UPDATE... 【参考方案1】:

您可以使用解析函数row_number() 和rowid 来获取行数:

UPDATE test_dup
   SET done = 'error'
 WHERE ROWID IN (SELECT ROWID
                   FROM (SELECT acc_num, tel_num, imsi, ROW_NUMBER () OVER (PARTITION BY acc_num, tel_num, imsi ORDER BY acc_num) AS ROW_NUMBER FROM test_dup)
                  WHERE ROW_NUMBER > 1)

【讨论】:

感谢您的回复,它按预期工作,您能否解释一下 rowid 和 drow_number 在这里是如何工作的?我认为我的 ROWID 概念仍然不清楚,因为我无法使用它们! @mradul 您是否阅读了我的答案中的链接提示 row_numer 和 rowid 单词?如果你有,问我你有什么不明白的。 @Motor-- 是的,现在我得到了这里的逻辑 row_number 函数根据分析函数内的 acc_num,tel_num,imsi 列为每个行集分配一个不同的数字,然后在 where 子句中我们说 row_number >1所以它会在 rowid 的帮助下更新 row_number >1 的行 @mradul 是的,分析函数可以在分区上工作。在这种情况下,数据在 acc_num、tel_num、imsi 上进行分区。这意味着,acc_num、tel_num、imsi 的每个不同组合都是一组。在这里,row_number 从一个开始在每个组中计数。因此,我们得到行号 > 1 的行的 rowid。我们将每个组中的第一个保持不变。 rowid 唯一标识了数据库记录,我们使用它来更新这些记录。

以上是关于如果有重复记录,则更新同一表的列的主要内容,如果未能解决你的问题,请参考以下文章

CodeIgniter - 如果新的或更新的重复记录则插入活动记录

通过比较sql server中同一张表的每条记录返回重复

根据另一张表的更新更新一张表的记录[重复]

我们如何处理在表的所有记录中具有相同值的列?

如果相同的列值在多行中重复,则 UPDATE - SQL / MYSQL

如果 mysql 数据库中的表中不存在,则更新或插入多条记录