带有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 

但是这也是因为工会而不起作用的。

如何使用SQL Server 2008 R2中的ROW_NUMBER()函数更新列?

还有一个select

 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看起来像recursionCTE ,因为它本质上是自引用的。 recursionCTE必须具有需要使用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 

这是@Aleksandr Fedorenko的答案添加了一个WHERE子句的修改版本:

 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子句使得它只是跳过值没有改变的行。 我不得不说,我惊讶于它可以运行我的查询有多快。

免责声明:我不是数据库专家,我使用PARTITION BY为我的子句,所以它可能不完全相同的结果为这个查询。 对于我来说,有问题的列是客户的付款订单,所以一旦设置,价值一般不会改变。

还要确保你有索引,特别是如果你在SELECT语句上有一个WHERE子句。 过滤索引对我来说很好,因为我根据付款状态进行过滤。


我的查询使用PARTITION

 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 

如果列不是空的,则不需要'IS NOT NULL'部分。


当我说性能提升是巨大的时,我的意思是在更新less量的行时基本上是瞬时的。 有了正确的索引,我能够实现与“内部”查询所花费的时间相同的更新:

  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 

简单和简单的方法来更新游标

 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