Как исправить большое количество повторяющихся записей

#sql-server

#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)
  

Вышеуказанное отлично работает для первого идентификатора в списке, но обновляет остальные записи с тем же 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.

Я также попытался обернуть вышеуказанное в курсор, думая, что запрос не получает возможности обновить с помощью правильного sequence_no для следующего идентификационного номера, но это тоже не сработало

Комментарии:

1. пожалуйста, предоставьте схему таблицы.

2. Что вы на самом деле пытаетесь сделать с повторяющимися строками? Вы пытаетесь обновить все порядковые номера? Примеры данных и ожидаемые результаты здесь действительно помогут.

3. попробуйте partition by t.id , а также можете ли вы создать [SQLFiddle](www.sqlfiddle.com ) для получения данных?

4. Прошу прощения, я предоставлю дополнительную информацию через минуту

Ответ №1:

Мне удалось решить эту проблему, используя следующий код:

 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 для первой записи.