使用借记贷方和上一行SQL Server 2012运行总计

时间:2015-07-21 18:20:18

标签: tsql sql-server-2012 running-total

我在重新计算运行总计方面遇到了问题。

我的情况是我们有重复的交易,必须删除这些交易,并且必须根据金额重新计算初始和期末余额,并考虑isdebit时的情况。

我的尝试是嵌套游标(父子)和父选择所有不同的bookingNo和孩子的计算看起来非常混乱我没有工作,没有发布它因为我不想混淆事情。

我知道在SQL Server 2012中你可以使用(sum over partition by),但我无法弄清楚如何处理已删除的行等。

以下是我到目前为止所做的事情

    --Create Table for testing
    IF object_id(N'TestTransaction', 'U') IS NOT NULL  DROP TABLE TestTransaction

    GO
    CREATE TABLE [TestTransaction]
    (
        [Id] [bigint] IDENTITY(1,1) NOT NULL,
        [BookingNo] [bigint] NOT NULL,
        [IsDebit] [bit] NOT NULL,
        [Amount] [decimal](18, 2) NOT NULL,
        [InitialBalance] [decimal](18, 2) NOT NULL,
        [ClosingBalance] [decimal](18, 2) NOT NULL
    ) ON [PRIMARY]
    GO

    INSERT [TestTransaction] ([BookingNo], [IsDebit], [Amount], [InitialBalance], [ClosingBalance]) 
    SELECT 200, 0, 100, 2000,2100 UNION ALL
    SELECT 200, 0, 100, 2100,2200 UNION ALL 
    SELECT 200, 1, 150, 2150,2000 UNION ALL 
    SELECT 200, 0, 300, 2000,2300 UNION ALL 
    SELECT 200, 0, 400, 2300,2700 UNION ALL 
    SELECT 200, 0, 250, 2700,2950 UNION ALL 
    SELECT 200, 0, 250, 2950,3200

--- end of setup

IF OBJECT_ID('tempdb..#tmpTransToDelete') IS NOT NULL DROP TABLE #tmpTransToDelete
GO
CREATE TABLE #tmpTransToDelete
(   BoookingNo bigint,
    Isdebit bit,
    amount decimal(18,2),
    InitialBalance decimal(18,2),
    ClosingBalance decimal(18,2)
)

DECLARE @RunnnigInitialBalance decimal(18,2),@RunnnigClosingBalance decimal(18,2)

INSERT #tmpTransToDelete(BoookingNo,Isdebit,amount,InitialBalance,ClosingBalance)
SELECT BookingNo,Isdebit,amount,InitialBalance,ClosingBalance
FROM TestTransaction 
WHERE ID IN (1,6)

--Delete all duplicate transaction (just to prove the point)
DELETE  TestTransaction WHERE ID IN (1,6)

-- now taking into account the deleted rows recalculate the lot and update the table.

有任何帮助吗?建议?

编辑 结果应该是

    Id  BookingNo   IsDebit Amount  InitialBalance  ClosingBalance
    2   200         0       100.00  2000.00         2000.00
    3   200         1       150.00  2000.00         2150.00
    4   200         0       300.00  2150.00         2450.00
    5   200         0       400.00  2450.00         2850.00
    7   200         0       250.00  2600.00         2850.00

2 个答案:

答案 0 :(得分:0)

以下是使用您的数据运行总计的示例:

SELECT BookingNo
    , Amount 
    , IsDebit
    , SUM(Amount * IIF(IsDebit = 0, 1, -1)) OVER (PARTITION BY BookingNo ORDER BY Id ROWS UNBOUNDED PRECEDING) AS RunningTotal

FROM TestTransaction

答案 1 :(得分:0)

如果存在影响初始余额的交易数据,我之前的回复中的RunningTotal方法将起作用。但是,由于显然不是这种情况,我会说你不能删除任何行而不将相对差异应用于所有后续行作为同一事务的一部分。此外,我确信您的初始样本数据是错误的,这只会加剧混乱。在我看来它应该如下:

SELECT 200, 0, 100, 2000,2100 UNION ALL
SELECT 200, 0, 100, 2100,2200 UNION ALL 
SELECT 200, 1, 150, 2200,2050 UNION ALL 
SELECT 200, 0, 300, 2050,2350 UNION ALL 
SELECT 200, 0, 400, 2350,2750 UNION ALL 
SELECT 200, 0, 250, 2750,3000 UNION ALL 
SELECT 200, 0, 250, 3000,3250

经过纠正,以下是我编写删除和更新事务的方法:

BEGIN TRAN

DECLARE @tbd TABLE (
    Id bigint
    ,BookingNo bigint
    ,Amount decimal(18,2)
    );

DELETE FROM TestTransaction
OUTPUT deleted.Id
, deleted.BookingNo
, deleted.Amount * IIF(deleted.IsDebit = 0, 1, -1) AS Amount
INTO @tbd
WHERE ID IN (1,6);

WITH adj 
AS (
    SELECT tt.BookingNo, tt.Id, SUM(tbd.amount) AS Amount
    FROM TestTransaction tt 
    JOIN @tbd tbd ON tt.BookingNo = tbd.BookingNo AND tbd.id <= tt.id
    GROUP BY tt.BookingNo, tt.Id
    )

UPDATE tt
SET InitialBalance -= adj.Amount
    ,ClosingBalance -= adj.Amount
FROM TestTransaction tt
JOIN adj ON tt.BookingNo = adj.BookingNo AND tt.Id = adj.Id;

COMMIT TRAN

产生最终结果:

Id  BookingNo   IsDebit Amount  InitialBalance  ClosingBalance
2   200 0   100.00  2000.00 2100.00
3   200 1   150.00  2100.00 1950.00
4   200 0   300.00  1950.00 2250.00
5   200 0   400.00  2250.00 2650.00
7   200 0   250.00  2650.00 2900.00