'SQL update value from previous row dynamically

I'm trying to update a value to equal the previous row's value within that PrimaryID group - but the previous row could also be updated based on my query. I can do it with a loop or cursor but for the few-million rows I'm dealing with, it just takes too long. I've used the CTE with LAG function described below but it's static and won't take into account values I've already updated.



declare @table table (PrimaryID int, SecondaryID int, Val decimal(10,2))
insert into @table values
(1,1,100),
(1,2,150),
(1,3,null),
(2,1,50),
(2,2,null),
(2,3,null),
(2,4,60),
(2,5,null),
(2,6,null)

;WITH cte AS
(
    SELECT PrimaryID, SecondaryID, LAG(Val, 1) OVER (PARTITION BY PrimaryID ORDER BY SecondaryID) previousVal FROM @table
)
UPDATE  t
SET     Val = cte.previousVal
FROM    @table t
JOIN    cte ON t.PrimaryID = cte.PrimaryID AND t.SecondaryID = cte.SecondaryID 
WHERE   t.SecondaryID > 1 
AND     t.Val IS NULL

select * from @table

initial data

PrimaryID SecondaryID Value
1 1 100
1 2 NULL
1 3 NULL
2 1 50
2 2 NULL
2 3 NULL
2 4 60
2 5 NULL
2 6 NULL

expected outcome

Primary ID Secondary ID Value
1 1 100
1 2 100
1 3 100
2 1 50
2 2 50
2 3 50
2 4 60
2 5 60
2 6 60

actual outcome

PrimaryID SecondaryID Value
1 1 100
1 2 100
1 3 NULL
2 1 50
2 2 50
2 3 NULL
2 4 60
2 5 60
2 6 NULL


Solution 1:[1]

use APPLY operator to find the last not null value to update back the table

UPDATE  t
SET     Val = v.Val
FROM    @table t
        CROSS APPLY
        (
             SELECT TOP 1 x.Val
             FROM   @table x
             WHERE  x.PrimaryID = t.PrimaryID
             AND    x.SecondaryID < t.SecondaryID
             AND    x.Val IS NOT NULL
             ORDER BY x.SecondaryID DESC
        ) v
WHERE   t.Val IS NULL

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Squirrel