答案 0 :(得分:5)
您需要的东西称为aggregate windowing function,特别是SUM ... OVER
。
问题在于,仅当您可以确定性地指定行的顺序时,这样的“运行总计”才有意义。示例数据不包括可用于提供此所需排序的属性。表本身没有明确的顺序。
如果您有输入日期栏之类的内容,则可以使用以下解决方案:
DECLARE @T table
(
EntryDate datetime2(0) NOT NULL,
Purchase money NULL,
Sale money NULL
);
INSERT @T
(EntryDate, Purchase, Sale)
VALUES
('20180801 13:00:00', $1000, NULL),
('20180801 14:00:00', NULL, $400),
('20180801 15:00:00', NULL, $400),
('20180801 16:00:00', $5000, NULL);
SELECT
T.Purchase,
T.Sale,
Remaining =
SUM(ISNULL(T.Purchase, $0) - ISNULL(T.Sale, 0)) OVER (
ORDER BY T.EntryDate
ROWS UNBOUNDED PRECEDING)
FROM @T AS T;
演示:db<>fiddle
在窗口框架中使用ROWS UNBOUNDED PRECEDING
是ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
的简写。与默认ROWS
相比,RANGE
is different的行为是重复的(通常是better-performing)。有很强的论据说ROWS
应该是默认值,但这不是我们得到的。
有关更多信息,请参见Itzik Ben-Gan的How to Use Microsoft SQL Server 2012's Window Functions及其出色的book。
答案 1 :(得分:-1)
您应该至少抛出10条具有不同测试用例的记录,以使观点很清楚。
如果实际表中已经有Increment id
字段,则不需要CTE
。
增量字段不必为串行
Sql Server 2008
及以下,
DECLARE @T table
(
Purchase int NULL,
Sale int NULL
);
INSERT @T
(Purchase, Sale)
VALUES
(1000, NULL),
(NULL, 400),
(NULL, 400),
(5000, NULL);
;with CTE as
(
select *
,ROW_NUMBER()OVER(ORDER BY (SELECT NULL))rn
from @T
)
SELECT c.purchase,c.sale
--,c.rn
,case when rn=1 then c.purchase
else c1.Remained
end Remained
FROM cte c
OUTER APPLY(
SELECT
sum(isnull(purchase,0))- sum(isnull(sale,0) )Remained
FROM cte c1 WHERE c1.rn<=c.rn
)c1