如何更正大量重复记录

时间:2019-04-09 10:12:51

标签: sql-server

我正在尝试更正SQL Server中的大量重复记录,是否有办法将其作为批量更新而不是为每一行运行更新脚本?

数据如下:

client | voucher_no | sequence_no | id
-------+------------+-------------+------
AA     | 11111111   | 1           | 0001
AA     | 11111111   | 1           | 0002 
AA     | 11111111   | 1           | 0003
AA     | 11111112   | 13          | 0004
AA     | 11111112   | 13          | 0004
AA     | 11111113   | 28          | 0005
AA     | 11111113   | 28          | 0006
AA     | 11111114   | 17          | 0007
AA     | 11111114   | 17          | 0008
AA     | 11111115   | 23          | 0009
AA     | 11111115   | 23          | 0010

我一直试图找到一种一次性更新记录的方法,这样脚本的结果将是:

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


UPDATE table_a
SET sequence_no = (SELECT ROW_NUMBER() OVER (PARTITION BY sequence_no ORDER BY t.client, t.voucher_no, t.sequence_no ))
                   FROM table_a AS t
                   WHERE t.id IN (0002, 0003, 0005, 0007, 0009, 0011)

上面的方法对于列表中的第一个ID可以正常工作,但是它使用与第一个相同的sequence_no更新其余记录。

所以我最终得到了

client | voucher_no | sequence_no | id
-------+------------+-------------+------
AA     | 11111111   | 2           | 0002 
AA     | 11111111   | 2           | 0003
AA     | 11111112   | 2           | 0005
AA     | 11111113   | 2           | 0007
AA     | 11111114   | 2           | 0009
AA     | 11111115   | 2           | 0011

如果将序列号更新为该客户端和voucher_no组合已经存在的序列号,这可能会引起进一步的问题。

我也尝试过将以上内容包装在光标中,以为查询没有机会使用下一个ID号的正确sequence_no更新,但这也不起作用

1 个答案:

答案 0 :(得分:0)

我设法通过使用以下代码解决了这个问题:

DECLARE @client VARCHAR(2)
DECLARE @voucher_no INT 
DECLARE @sequence_no INT
DECLARE @id INT 


DECLARE cursor_results CURSOR FOR 
WITH T AS 
(
    SELECT *, COUNT(*) OVER (PARTITION BY client, voucher_no, sequence_no) AS cnt 
      FROM table_a 
)

  SELECT t.client, t.voucher_no, t.sequence_no,t.id
    FROM T AS t 
   WHERE t.cnt > 1
   AND agrtid IN (0002, 0003, 0005, 0007, 0009, 0011) 
ORDER BY t.client, t.voucher_no, t.sequence_no DESC 

OPEN cursor_results 
FETCH NEXT FROM cursor_results INTO @client, @voucher_no, @sequence_no, @id
WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @new_sequence_no INT = (SELECT MAX(sequence_no) + 1 FROM table_a WHERE client = @client AND voucher_no = @voucher_no)
    UPDATE table_a
       SET sequence_no = @new_sequence_no,
           last_update = GETDATE(),
           user_id = 'USR' 
     WHERE id = @id 
       AND client = @client 
       AND voucher_no = @voucher_no

FETCH NEXT FROM cursor_results INTO @client, @voucher_no, @sequence_no, @id
END 

CLOSE cursor_results 
DEALLOCATE cursor_results

虽然这可能不是使用游标解决此问题的最佳方法,但允许我逐步浏览记录并逐个更新它们,然后再移至下一个。

以这种方式设置@new_sequence_no还可以确保我为当时的记录获取正确的MAX(sequence_no)+ 1,而不是为所有重复项都赋予第一个MAX(sequence_no)+ 1。记录。