带row_number()的SQL更新

时间:2012-11-30 16:14:59

标签: sql-server sql-server-2008-r2 sql-update

我想用增量号更新我的列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()函数更新列?

10 个答案:

答案 0 :(得分:152)

还有一个选择

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

答案 1 :(得分:55)

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/

答案 2 :(得分:38)

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

答案 3 :(得分:15)

您的第二次尝试失败主要是因为您将CTE命名为与基础表相同并使CTE看起来好像是递归CTE ,因为它基本上引用了它自己。 recursive 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

答案 4 :(得分:13)

这是@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 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

如果列不可为空,则不需要“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

答案 5 :(得分:1)

更新光标的简单方法

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

答案 6 :(得分:1)

我是根据自己的情况做的并且工作了

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

答案 7 :(得分:1)

如果表没有关系,只需将所有复制到具有行号的新表中,然后删除旧表,并用旧表重命名新表。

从以下位置选择RowNum = ROW_NUMBER()OVER(ORDER BY(SELECT NULL)),* INTO cdm.dbo.SALES2018 ( 从SALE2018中选择*)作为SalesSource

答案 8 :(得分:1)

在我的例子中,我添加了一个新列,并想用整个表的 equevilat 记录号更新它

id  name       new_column (ORDER_NUM)
1   Ali        null
2   Ahmad      null
3   Mohammad   null
4   Nour       null
5   Hasan      null
6   Omar       null

我写这个查询是为了用行号填充新列

UPDATE My_Table
SET My_Table.ORDER_NUM  = SubQuery.rowNumber
FROM (
         SELECT id ,ROW_NUMBER() OVER (ORDER BY [id]) AS rowNumber
         FROM My_Table
     ) SubQuery
INNER JOIN My_Table ON
        SubQuery.id = My_Table.id

执行此查询后,我的新列中有 1,2,3,... 数字

答案 9 :(得分:0)

我用第一次出现的零件更新临时表,其中多个零件可以与一个序列号相关联。 RowId=1 返回我使用零件和序列号加入 tmp 表和数据的第一次出现。

update #Tmp
set 
#Tmp.Amount=@Amount
from 
(SELECT Part, Row_Number()   OVER (ORDER BY [Part]) AS RowId FROM #Tmp
where Sequence_Num=@Sequence_Num
)data
where data.Part=#Tmp.Part
and data.RowId=1
and #Tmp.Sequence_Num=@Sequence_Num