假设这张表:
CREATE TABLE Operation (
Id int PRIMARY KEY,
Change int,
PreviousId int null FOREIGN KEY REFERENCES Operation(id),
PreviousAmount int null,
NewAmount AS (COALESCE(PreviousAmount,0) + Change) PERSISTED
);
有了这些数据:
INSERT INTO Operation (Id, Change, PreviousId, PreviousAmount)
VALUES
(1, 1, null, null),
(2, 2, 1, 1),
(3, 3, 2, 3),
(4, 4, 3, 5);
到目前为止 PreviousAmount 和 NewAmount 有有效数据:
id change previousId previousAmount newAmount
-------------------------------------------------
1 1 NULL NULL 1
2 2 1 1 3
3 3 2 3 6
4 4 3 5 9
假设我们更新第一行“change”:
Update Operation set Change=10 where id=1
我想要一个触发器来更新行链中的所有 PreviousAmount,以便每一行在其“PreviousAmount”内保存上一行更新的“NewAmount”
仅给出原始 id 和 change 列,您可以使用 窗口函数
LAG()
和 SUM()
来选择 previousId、previousAmount 和 newAmount 值。
窗口
SUM()
函数(具有 OVER()
限定符)通常会为您提供当前行的运行总计,但可以通过向 ROWS
添加 OVER()
规范来调整此范围,以产生通过前一行运行总和。
结果查询将是:
SELECT
D.id,
D.change,
LAG(id) OVER(ORDER BY id) AS previousId,
SUM(change) OVER(
ORDER BY id
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
) AS PreviousAmount,
SUM(change) OVER(ORDER BY id) AS NewAmount
FROM Data D
ORDER BY D.id
如果(反对所有建议)您确实想将这些结果存储回表中,您可以运行以下
UPDATE
语句:
UPDATE D
SET
previousId = previousIdCalc,
previousAmount = previousAmountCalc,
newAmount = newAmountCalc
FROM (
SELECT
D.*,
LAG(id) OVER(ORDER BY id) AS previousIdCalc,
SUM(change) OVER(
ORDER BY id
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
) AS previousAmountCalc,
SUM(change) OVER(ORDER BY id) AS newAmountCalc
FROM Data D
) D
请参阅 this db<>fiddle 以获取选择和更新的演示。
结果:
id | 改变 | 上一个ID | 上一页金额 | 新金额 |
---|---|---|---|---|
1 | 1 | 空 | 空 | 1 |
2 | 2 | 1 | 1 | 3 |
3 | 3 | 2 | 3 | 6 |
4 | 4 | 3 | 6 | 10 |