更新查询 - 前行 x 和当前行 y 的总和
Posted
技术标签:
【中文标题】更新查询 - 前行 x 和当前行 y 的总和【英文标题】:Update Query - Sum of previous row x and current row y 【发布时间】:2021-10-16 13:14:27 【问题描述】:我有一个 LedgerData 表,需要更新余额。
表结构
CREATE TABLE [dbo].[LedgerData]
(
[Id] INT NOT NULL,
[CustomerId] INT NOT NULL,
[Credit] INT,
[Debit] INT,
[Balance] INT
CONSTRAINT [PK_dbo_LedgerData]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
样本数据
INSERT INTO [dbo].[LedgerData] VALUES (1, 1, 50, 0, 0);
INSERT INTO [dbo].[LedgerData] VALUES (2, 1, 0, 25, 0);
INSERT INTO [dbo].[LedgerData] VALUES (3, 2, 0, 75, 0);
INSERT INTO [dbo].[LedgerData] VALUES (4, 1, 0, 10, 0);
INSERT INTO [dbo].[LedgerData] VALUES (5, 2, 5, 0, 0);
INSERT INTO [dbo].[LedgerData] VALUES (6, 1, 10, 25, 0);
我尝试更新客户明智的余额列ORDER BY [Id] ASC
,但它没有按预期更新。我也探索了sql query to calculate sum and add sum from previous rows
请帮我计算余额栏Balance = (Previous Row Balance + Credit - Debit)
【问题讨论】:
请将您的预期结果添加到您的问题中。 明确一点:id
是定义顺序的列,对吧?
停下来,只是不要。数据应保持无冗余以避免出现不一致的可能性。因此,将表格的部分集合上的总和写入其中并不是一件好事。删除列balance
。如果需要余额,可以随时查询得到正确的结果。为方便起见,您可以创建一个视图来存储此类查询,这样您就不必每次都重复它。
【参考方案1】:
理想情况下,这是你应该做的事情作为你INSERT
数据,通过获取以前的值(并锁定表,以便其他INSERT
语句不会发生以避免竞争) 然后为Balance
提供一个值。但是,您可以 UPDATE
具有累积 SUM
和可更新 CTE 的所有行:
WITH CTE AS(
SELECT ID,
CustomerID,
Balance,
0 + SUM(Credit) OVER (PARTITION BY CustomerID ORDER BY ID) - SUM(Debit) OVER (PARTITION BY CustomerID ORDER BY ID) AS NewBalance
FROM dbo.LedgerData)
UPDATE CTE
SET Balance = NewBalance;
GO
SELECT *
FROM dbo.LedgerData;
或者,根本不存储聚合值,并使用VIEW
,以便始终可以使用我在 CTE 中使用的相同表达式(准确地)计算该值。例如:
CREATE VIEW dbo.LedgerDataCumulative
AS
SELECT Id,
CustomerId,
Credit,
Debit,
SUM(Credit) OVER (PARTITION BY CustomerID ORDER BY ID) - SUM(Debit) OVER (PARTITION BY CustomerID ORDER BY ID) AS Balance
FROM dbo.LedgerData;
GO
【讨论】:
【参考方案2】:可以使用单个窗口函数执行更新。
with upd_cte as (
select *, sum([Credit]-[Debit]) over (partition by customerId order by id) sum_over
from #LedgerData)
update upd_cte
set Balance=sum_over;
【讨论】:
以上是关于更新查询 - 前行 x 和当前行 y 的总和的主要内容,如果未能解决你的问题,请参考以下文章