如何批量修正SQL Server中大量重复sequence_no记录
解决SQL Server批量修正重复sequence_no的问题
你的问题核心出在分区逻辑选错了——你用PARTITION BY sequence_no来分组,但实际上重复的sequence_no是隶属于同一个client+voucher_no组合的,应该按这两个字段分区才对。另外直接用子查询更新时,关联逻辑没处理好,导致所有匹配的行拿到了同一个计算值,这就是为什么你看到所有目标行的sequence_no都变成2的原因。
下面是高效的批量更新方案,用CTE(公共表表达式)生成每个分组内的递增序号,一次性完成所有修正:
WITH RankedRecords AS ( SELECT id, sequence_no, -- 按客户+凭证号分组,按id排序生成组内行号 ROW_NUMBER() OVER (PARTITION BY client, voucher_no ORDER BY id) AS row_num, -- 获取每个分组的初始sequence_no(即组内最小的序号值) MIN(sequence_no) OVER (PARTITION BY client, voucher_no) AS base_seq FROM table_a ) UPDATE RankedRecords SET sequence_no = base_seq + row_num - 1;
方案为什么有效:
- 分区逻辑精准:
PARTITION BY client, voucher_no确保我们只在需要修正重复的范围内(同一客户+同一凭证号)计算序号,不会干扰其他分组的数据。 - 行号生成有序:
ROW_NUMBER()按id排序给每个组内的记录分配1、2、3...的序号,保证修正后的序号顺序和你期望的一致(从旧id小的到id大的依次递增)。 - 序号计算合理:用分组的初始序号(
base_seq)加上行号减1,让组内第一条记录保持原序号,后续记录依次+1,完美匹配你想要的结果。
执行后结果验证:
运行脚本后,你的数据会变成:
| client | voucher_no | sequence_no | id |
|---|---|---|---|
| AA | 11111111 | 1 | 0001 |
| AA | 11111111 | 2 | 0002 |
| AA | 11111111 | 3 | 0003 |
| AA | 11111112 | 13 | 0004 |
| AA | 11111112 | 14 | 0005 |
| AA | 11111113 | 28 | 0006 |
| AA | 11111113 | 29 | 0007 |
| AA | 11111114 | 17 | 0008 |
| AA | 11111114 | 18 | 0009 |
| AA | 11111115 | 23 | 0010 |
| AA | 11111115 | 24 | 0011 |
完全符合你的预期,而且是批量一次性更新,不需要游标或逐行处理,效率远高于逐行执行脚本。
如果你只想更新存在重复的分组(避免对无重复的记录做无意义更新),可以在CTE里加过滤条件:
WITH RankedRecords AS ( SELECT id, sequence_no, ROW_NUMBER() OVER (PARTITION BY client, voucher_no ORDER BY id) AS row_num, MIN(sequence_no) OVER (PARTITION BY client, voucher_no) AS base_seq, COUNT(*) OVER (PARTITION BY client, voucher_no) AS group_count FROM table_a ) UPDATE RankedRecords SET sequence_no = base_seq + row_num - 1 WHERE group_count > 1; -- 仅更新有重复记录的分组
内容的提问来源于stack exchange,提问作者srhodg
相关产品推荐
相关产品推荐

