[sql-server] row_number ()를 사용한 SQL 업데이트

CODE_DEST 열을 증분 번호로 업데이트하고 싶습니다. 나는 가지고있다:

CODE_DEST   RS_NOM
null        qsdf
null        sdfqsdfqsdf
null        qsdfqsdf

다음과 같이 업데이트하고 싶습니다.

CODE_DEST   RS_NOM
1           qsdf
2           sdfqsdfqsdf
3           qsdfqsdf

이 코드를 시도했습니다.

UPDATE DESTINATAIRE_TEMP
SET CODE_DEST = TheId
FROM (SELECT  Row_Number()   OVER (ORDER BY [RS_NOM]) AS TheId FROM DESTINATAIRE_TEMP)

이것은 때문에 작동하지 않습니다 )

나는 또한 시도했다 :

WITH DESTINATAIRE_TEMP AS
  (
    SELECT
    ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
    FROM DESTINATAIRE_TEMP
  )
UPDATE DESTINATAIRE_TEMP SET CODE_DEST=RN

그러나 이것은 또한 결합 때문에 작동하지 않습니다.

ROW_NUMBER()SQL Server 2008 R2 의 함수를 사용하여 열을 업데이트하려면 어떻게 해야합니까?



답변

하나 더 옵션

UPDATE x
SET x.CODE_DEST = x.New_CODE_DEST
FROM (
      SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST
      FROM DESTINATAIRE_TEMP
      ) x


답변

DECLARE @id INT
SET @id = 0
UPDATE DESTINATAIRE_TEMP
SET @id = CODE_DEST = @id + 1
GO 

이 시도

http://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/


답변

With UpdateData  As
(
SELECT RS_NOM,
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE DESTINATAIRE_TEMP SET CODE_DEST = RN
FROM DESTINATAIRE_TEMP
INNER JOIN UpdateData ON DESTINATAIRE_TEMP.RS_NOM = UpdateData.RS_NOM


답변

두 번째 시도는 기본 테이블과 동일한 CTE 이름을 지정하고 본질적으로 자체를 참조했기 때문에 CTE재귀 CTE 인 것처럼 보이게했기 때문에 실패했습니다 . 재귀 CTE는 의 사용을 요구하는 특정 구조 있어야 UNION ALL집합 연산자.

대신 CTE에 다른 이름을 지정하고 대상 열을 추가 할 수 있습니다.

With SomeName As
(
SELECT
CODE_DEST,
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE SomeName SET CODE_DEST=RN


답변

이것은 WHERE 절을 추가하는 @Aleksandr Fedorenko의 답변의 수정 된 버전입니다.

UPDATE x
SET x.CODE_DEST = x.New_CODE_DEST
FROM (
      SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST
      FROM DESTINATAIRE_TEMP
      ) x
WHERE x.CODE_DEST <> x.New_CODE_DEST AND x.CODE_DEST IS NOT NULL

WHERE 절을 추가함으로써 후속 업데이트에서 성능이 크게 향상되었음을 알았습니다. Sql Server는 값이 이미 존재하더라도 행을 업데이트하는 것처럼 보이고 그렇게하는 데 시간이 걸리므로 where 절을 추가하면 값이 변경되지 않은 행을 건너 뛰게됩니다. 내 쿼리를 얼마나 빨리 실행할 수 있는지에 대해 놀랐습니다.

면책 조항 : 저는 DB 전문가가 아니며 제 절에 PARTITION BY를 사용하고 있으므로이 쿼리에 대해 정확히 동일한 결과가 아닐 수 있습니다. 나에게 문제의 열은 고객의 유료 주문이므로 일반적으로 일단 설정되면 값이 변경되지 않습니다.

특히 SELECT 문에 WHERE 절이있는 경우 인덱스가 있는지 확인하십시오. 필터링 된 인덱스는 지불 상태를 기준으로 필터링했기 때문에 저에게 효과적이었습니다.


PARTITION by

UPDATE  UpdateTarget
SET     PaidOrderIndex = New_PaidOrderIndex
FROM
(
    SELECT  PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex
    FROM    [Order]
    WHERE   PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null
) AS UpdateTarget

WHERE UpdateTarget.PaidOrderIndex <> UpdateTarget.New_PaidOrderIndex AND UpdateTarget.PaidOrderIndex IS NOT NULL

-- test to 'break' some of the rows, and then run the UPDATE again
update [order] set PaidOrderIndex = 2 where PaidOrderIndex=3

열이 Null을 허용하지 않는 경우 ‘IS NOT NULL’부분은 필요하지 않습니다.


성능 향상이 엄청 났다고 말하면 적은 수의 행을 업데이트 할 때 본질적으로 즉각적이었습니다. 올바른 인덱스를 사용하여 ‘내부’쿼리가 자체적으로 수행하는 것과 동일한 시간이 걸리는 업데이트를 얻을 수있었습니다.

  SELECT  PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex
    FROM    [Order]
    WHERE   PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null


답변

나는 내 상황을 위해 이것을하고 일했습니다.

WITH myUpdate (id, myRowNumber )
AS
(
    SELECT id, ROW_NUMBER() over (order by ID) As myRowNumber
    FROM AspNetUsers
    WHERE  UserType='Customer'
 )

update AspNetUsers set EmployeeCode = FORMAT(myRowNumber,'00000#')
FROM myUpdate
    left join AspNetUsers u on u.Id=myUpdate.id


답변

커서를 업데이트하는 간단하고 쉬운 방법

UPDATE Cursor
SET Cursor.CODE = Cursor.New_CODE
FROM (
  SELECT CODE, ROW_NUMBER() OVER (ORDER BY [CODE]) AS New_CODE
  FROM Table Where CODE BETWEEN 1000 AND 1999
  ) Cursor