繁体   English   中英

根据上一行中的值更新值

[英]Update value based on value in previous row

我有下表:

CREATE TABLE dbo.Persons 
(
     [Date] date null, 
     [PersonId] int null, 
     [Amount] int null, 
     [Value] int null
)

这是一些示例数据:

INSERT INTO dbo.Persons ([Date], [PersonId], [Amount], [Value])
VALUES
('2020-01-01', 1, 200, NULL),
('2020-01-02', 1, 300, NULL),
('2020-01-03', 1, 400, NULL),
('2020-01-04', 1, 500, NULL),
('2020-01-01', 2, 200, NULL),
('2020-01-02', 2, 300, NULL),
('2020-01-03', 2, 400, NULL),
('2020-01-04', 2, 500, NULL),
('2020-01-01', 3, 0, NULL),
('2020-01-02', 3, 0, NULL),
('2020-01-03', 3, 0, NULL),
('2020-01-04', 3, 0, NULL)

我的目标:根据其他列中的值和 [Value] 列中的先前值更新 [Value] 列中的所有值。 主键是date+personId

用伪代码解释,我的逻辑需要类似:

CASE 
    WHEN [Amount] > 200 AND previous row value IN [Value] = 1, then 2
    WHEN [Amount] > 500 AND previous row value in [Value] = 2, then 3
    WHEN [Date] > '2020-01-01' AND [Amount] = 500 AND previous row value in [Value] = 2, then 4

等等 - 这捕获了一般的 T-SQL 代码逻辑..

我也只想更新[Value]为 NULL 的[Value]列。

这里有什么戏? 我读过有关使用 LAG、While LOOP、递归 CTE 等的信息,但不确定 go 的位置。

您可以使用lag来引用前一行的值。 在您的示例中,数据value将保持为null尽管您的case逻辑取决于前一行,即null开始。

但是,这就是你可以接近它的方式

with u as (
    select [Date], PersonId,
    case
        when Amount > 200 and Lag(Value) over(partition by PersonId order by [Date]) = 1 then 2
        when Amount > 500 and Lag(Value) over(partition by PersonId order by [Date]) = 2 then 3
        when [Date] > '20200101' and Amount = 500 and Lag(Value) over(partition by PersonId order by [Date])= 2 then 4
    end [Value]
    from Persons
)
update p set
    p.Value=u.Value
from u join Persons p on p.[Date]=u.[Date] and p.PersonId=u.PersonId

您可以添加行号,然后自行加入。 您可以将此想法扩展到第 2 行、第 3 行等。

With Qry1 (
    Select  -- Columns from Person table
            , ROWNUMBER() OVER(PARTITION BY PersonId ORDER BY Date) As Seq
    FROM Persons
)
Select  -- Columns from ThisRow
        -- Columns from PrevRow (values will be null if there is
        -- no previous row for this PersonId and Date)
FROM Qry1 ThisRow
LEFT JOIN Qry1 PrevRow
ON ThisRow.PersonId = PrevRow.PersonId
AND ThisRow.Date = PrevRow.Date
AND ThisRow.Seq - 1 = PrevRow.Seq 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM