如何循环遍历表并更新 SQL 中的字段

Chr*_*zuk 5 sql-server

我需要根据accountId表中的以 1 开头的序列号更新一列。我该怎么做呢?

所以OrderIDNULL开始。所以对于每一行AccountID我需要更新OrderID从 1 开始并按顺序更新,所以我的数据是这样出来的。该表被称为Renewals

RowID  AccountID  OrderID
1      A          1
2      A          2
4      A          3
5      B          1
6      B          2
7      C          1
Run Code Online (Sandbox Code Playgroud)

Sql*_*Zim 8

使用公用表表达式with row_number()to partition byAccountId和 order by [RowId]

;with cte as (
  select *
    ,  NewOrderId = row_number() over (
          partition by AccountId
          order by [RowId]
    )
  from Renewals
)
update cte
  set OrderId = NewOrderId;
Run Code Online (Sandbox Code Playgroud)

不使用公用表表达式:

update r
  set OrderId = NewOrderId
  from (
    select *
      ,  NewOrderId = row_number() over (
            partition by AccountId
            order by [RowId]
      )
    from Renewals
      ) as r
Run Code Online (Sandbox Code Playgroud)

测试设置:http : //rextester.com/FSUD49402

create table Renewals (
    [RowId]   int     not null
  , AccountId char(1) not null
  , OrderId   int         null
);
insert into Renewals (RowId, AccountId) values
  (1,'A'), (2,'A'), (4,'A')
, (5,'B'), (6,'B'), (7,'C');

with cte as (
  select 
       [RowId]
    ,  AccountId
    ,  OrderId
    ,  NewOrderId = row_number() over (
          partition by AccountId
          order by [RowId]
    )
  from Renewals
)

update cte
  set OrderId = NewOrderId;

select * from Renewals;
Run Code Online (Sandbox Code Playgroud)

结果是:

+-------+-----------+---------+
| RowId | AccountId | OrderId |
+-------+-----------+---------+
|     1 | A         |       1 |
|     2 | A         |       2 |
|     4 | A         |       3 |
|     5 | B         |       1 |
|     6 | B         |       2 |
|     7 | C         |       1 |
+-------+-----------+---------+
Run Code Online (Sandbox Code Playgroud)

要回答此答案的评论中的问题:

我正在使用此数据来更新上一行。[...] 我试图表明上面的第 1 行被第 2 行更新被第 4 行替换,第 4 行尚未更新

可以通过以下方式完成:

select 
    r.*
  , RenewedBy=p.RowId 
from Renewals as r 
  left join Renewals as p 
    on p.AccountId = r.AccountId 
   and p.OrderId = r.OrderId+1
Run Code Online (Sandbox Code Playgroud)

返回:

+-------+-----------+---------+-----------+
| RowId | AccountId | OrderId | RenewedBy |
+-------+-----------+---------+-----------+
|     1 | A         |       1 | 2         |
|     2 | A         |       2 | 4         |
|     4 | A         |       3 | NULL      |
|     5 | B         |       1 | 6         |
|     6 | B         |       2 | NULL      |
|     7 | C         |       1 | NULL      |
+-------+-----------+---------+-----------+
Run Code Online (Sandbox Code Playgroud)

如果这是前一个的唯一原因update,我们根本不必到update桌子上。这将得到与上面相同的结果:

;with cte as (
  select *
    ,  rn = row_number() over (
          partition by AccountId
          order by [RowId]
    )
  from Renewals
)
select 
    r.RowId
  , r.AccountId
  , OrderId = r.rn
  , RenewedBy=p.RowId 
from cte as r 
  left join cte as p 
    on p.AccountId = r.AccountId 
   and p.rn = r.rn+1
Run Code Online (Sandbox Code Playgroud)


Sco*_*red 0

这对你有用吗?

set nocount on
Declare @Renewals table (RowId int, AccountId varchar(10), OrderId int)

insert into @Renewals (RowId, AccountId, OrderId) values (1,'A',null)
insert into @Renewals (RowId, AccountId, OrderId) values (2,'A',null)
insert into @Renewals (RowId, AccountId, OrderId) values (4,'A',null)
insert into @Renewals (RowId, AccountId, OrderId) values (5,'B',null)
insert into @Renewals (RowId, AccountId, OrderId) values (6,'B',null)
insert into @Renewals (RowId, AccountId, OrderId) values (7,'C',null)

UPDATE a
SET OrderId = (
        SELECT count(*) + 1
        FROM @Renewals
        WHERE AccountId = a.AccountId
            AND RowId < a.RowId
        )
FROM @Renewals a

SELECT *
FROM @Renewals
Run Code Online (Sandbox Code Playgroud)