如何用SQL Server 2012批量重编发票明细行号
批量重编发票行号的解决方案
嘿,这个需求我经常碰到!你现在用变量更新单张发票的方法完全没问题,但要批量处理所有存在重复行号的发票,用窗口函数会更高效、更简洁,不用逐个发票手动处理。
核心思路
利用ROW_NUMBER()窗口函数,按发票号(Invoice_Number)分组,给每个分组内的行生成从1开始的递增序号,然后直接更新原表的LineNum字段。
通用批量更新代码(SQL Server)
WITH UpdatedLines AS ( SELECT Invoice_Number, LineNum, -- 按发票号分组,生成新行号;如果需要保留原行的顺序,把(SELECT NULL)换成对应的排序字段(比如原LineNum、创建时间等) ROW_NUMBER() OVER (PARTITION BY Invoice_Number ORDER BY (SELECT NULL)) AS NewLineNum FROM Invoice_Itemized ) UPDATE UpdatedLines SET LineNum = NewLineNum;
只更新存在重复行号的发票
如果只想处理那些确实有重复LineNum的发票(避免无意义地更新所有行),可以先筛选出有重复的发票号,再进行更新:
-- 第一步:找出所有存在重复行号的发票 WITH DuplicateInvoices AS ( SELECT Invoice_Number FROM Invoice_Itemized GROUP BY Invoice_Number -- 分组后,去重的行号数量小于总行数,说明存在重复 HAVING COUNT(DISTINCT LineNum) < COUNT(*) ), -- 第二步:给这些发票的行重新编号 UpdatedLines AS ( SELECT i.Invoice_Number, i.LineNum, ROW_NUMBER() OVER (PARTITION BY i.Invoice_Number ORDER BY (SELECT NULL)) AS NewLineNum FROM Invoice_Itemized i JOIN DuplicateInvoices d ON i.Invoice_Number = d.Invoice_Number ) UPDATE UpdatedLines SET LineNum = NewLineNum;
注意事项
- 关于
ORDER BY:代码里的(SELECT NULL)是临时占位符,如果你的业务需要保留原行的顺序(比如按原来的LineNum从小到大,或者按录入时间排序),一定要把它替换成对应的字段,比如ORDER BY LineNum或者ORDER BY CreateTime,否则新行号的顺序可能是随机的。 - 性能对比:这种窗口函数的方法比循环处理每个发票要高效得多,尤其是数据量较大的时候,一次操作就能完成所有更新。
内容的提问来源于stack exchange,提问作者RDW
相关产品推荐
相关产品推荐

