2015-07-21 31 views
0

我在重新计算运行总计时遇到了问题。使用借记贷方和前一行运行总计SQL Server 2012

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

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

我知道在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 

回答

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 
+0

Jason APOLOGIES !!!你是正确的样本数据是错误的,我刚刚意识到这一点,因为我正在努力解决这个问题。我消化你的解决方案并回到你身边。无论如何,非常感谢你的回复时间 – developer9969

+0

有什么可说的。我仍然不相信没有游标,这很好。 – developer9969

+0

我可以问你一件事。你认为你的查询可以修改为重新调整Id,例如1-2-3-4等。而不是2-4-等等。明显地比将它移除为标识柱并且更加像LineNo。谢谢。我能想到的唯一方法是回到一个光标,并且您的解决方案非常简洁。感谢 – developer9969

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 
+0

嗨,谢谢你的时间,试图理解你做了什么我编辑了我应该期待的结果,那些不符合你的。看看我编辑的问题 – developer9969