带有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
尝试这个
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