使用另一个表中的use-once值更新一个表中的每一行的最快方法是什么?

vol*_*one 1 sql t-sql sql-server sql-server-2012 sql-server-2017

我有一个名为的表dbo.RecycleProductID只有一个主键ProductID列和一Used列:

ProductID (pk, int) | Used (bit)
23                    1   
65                    1
68                    1
90                    NULL
104                   NULL  
...
60983471              NULL
Run Code Online (Sandbox Code Playgroud)

上表中有大约6.5米的ProductID值,需要"回收"并分配给不同表格中的产品.一旦将a ProductID分配给产品,我必须更新Used列值1以指示它已被使用.ProductID序列中存在间隙,有些存在数千个(例如,它可以从1010跳到8055)并且此表中的行数多于接收dbo.Product表表.

dbo.Product表(大约1.5米行)只是一个产品列表,但没有ProductID值.

ProductID (pk, int)  | ProductName (varchar)
23                     Toothpaste
65                     Speakers
68                     Galaxy S8
NULL                   Plate
NULL                   Monitor
NULL                   Carpet
.....
Run Code Online (Sandbox Code Playgroud)

我目前正在运行的while循环,以获得ProductID从价值观dbo.RecycleProductIDdbo.Product表:

DECLARE @Max int = (select max(ProductID) from [dbo].[RecycleProductID]);
DECLARE @Min int = (select min(ProductID) from [dbo].[RecycleProductID]);

while @Min <= @Max 
begin

UPDATE TOP (1)
[dbo].[Product]
SET ProductID = (SELECT TOP 1 ProductID FROM [dbo].[RecycleProductID] b1 WHERE b1.Used IS NULL ORDER BY ProductID ASC)
OUTPUT INSERTED.ProductID INTO dbo.UsedProductID
WHERE 
ProductID is null;

UPDATE  
    rp1
SET    
    rp1.Used = 1
FROM
    [dbo].[RecycleProductID] rp1
INNER JOIN
    dbo.UsedProductID ub1 ON 
    ub1.ProductID = rp1.ProductID

set @Min = @Min+1
end;
Run Code Online (Sandbox Code Playgroud)

由于这基本上是一个游标,它需要永远.它已经运行了将近两天,只更新了大约326515行.有更快的方法吗?

uzi*_*uzi 5

试试这个查询:

with t1 as (
    select
        ProducID, row_number() over (order by ProducID) rn
    from 
        RecycleProductID
    where
        used is null
)
, t2 as (
    select
        ProducID, row_number() over (order by ProducID) rn
    from 
        Product
    where
        ProductID is null
)

update t2
set t2.ProducID = t1.ProducID
from
    t2
    join t1 on t2.rn = t1.rn
Run Code Online (Sandbox Code Playgroud)

编辑:此查询将更新RecycleProductID,可以单独执行

update RecycleProductID
set used = 1
where ProducID in (select ProductID from Product)
Run Code Online (Sandbox Code Playgroud)