查询列中包含购买和销售的运行总计

时间:2018-08-26 13:30:00

标签: sql-server sql-server-2016 running-total

我有一个如下表:

Table

如何使用Transact-SQL(按日期排序)在下面创建一列?

enter image description here

我正在使用SQL Server 2016。

2 个答案:

答案 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 PRECEDINGROWS 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