Sql server SQL Server动态重置运行平衡

Sql server SQL Server动态重置运行平衡,sql-server,tsql,Sql Server,Tsql,我目前的问题是,我有一个运行平衡,其中一个值低于另一个值,运行平衡需要重置。但不仅重置,而且使用另一个值作为其起始值,并再次启动天平 下表中包含数据: +-------------+--------+---------------------+-------------------+--------------+-------------+ | Tran_DateSK | Amount | Running_AccountFees | Overlimit_Balance | Restart_Cal

我目前的问题是,我有一个运行平衡,其中一个值低于另一个值,运行平衡需要重置。但不仅重置,而且使用另一个值作为其起始值,并再次启动天平

下表中包含数据:

+-------------+--------+---------------------+-------------------+--------------+-------------+
| Tran_DateSK | Amount | Running_AccountFees | Overlimit_Balance | Restart_Calc | Actual_Calc |
+-------------+--------+---------------------+-------------------+--------------+-------------+
|    20200217 |     39 |                  39 |           3867.76 |            0 |          39 |
|    20200217 |     50 |                  89 |           3867.76 |            0 |          89 |
|    20200316 |     39 |                 128 |           4735.52 |            0 |         128 |
|    20200316 |     50 |                 178 |           4735.52 |            0 |         178 |
|    20200324 |     50 |                 228 |           2685.52 |            0 |         228 |
|    20200330 |     50 |                 278 |             49.52 |            1 |       49.52 |
|    20200415 |     39 |                 317 |             49.52 |            1 |       49.52 |
|    20200515 |     39 |                 356 |           3917.28 |            0 |       88.52 |
|    20200515 |     50 |                 406 |           3917.28 |            0 |      138.52 |
|    20200519 |     50 |                 456 |           3467.28 |            0 |      188.52 |
|    20200604 |     50 |                 506 |           3017.28 |            0 |      238.52 |
|    20200609 |     50 |                 556 |           2167.28 |            0 |      288.52 |
|    20200611 |     50 |                 606 |             49.28 |            1 |       49.28 |
|    20200615 |     39 |                 645 |           3917.04 |            0 |       88.28 |
|    20200615 |     50 |                 695 |           3917.04 |            0 |      138.28 |
|    20200616 |     50 |                 745 |           3017.04 |            0 |      188.28 |
|    20200616 |     50 |                 795 |           3017.04 |            0 |      238.28 |
|    20200619 |     50 |                 845 |           2567.04 |            0 |      288.28 |
|    20200624 |     50 |                 895 |             47.04 |            1 |       47.04 |
|    20200715 |     39 |                 934 |             47.04 |            1 |       47.04 |
+-------------+--------+---------------------+-------------------+--------------+-------------+
实际计算是期望的结果,而往来账户费用是问题所在

往来账户费用是“金额”的往来余额,超限余额是测试。我们需要确保运行账户费用不超过上限

如果是,则取overlimits值并通过再次添加amount来重新开始计算

我的查询产生了以下结果:

    SELECT 
    [Transaction].ReportDateSK                              AS 'Tran_DateSK'
    ,[Transaction].AmountChange/100.00                      AS 'Amount'
    ,SUM([Transaction].AmountChange/100.00) 
        OVER (PARTITION BY [Transaction].AccountSK
        ORDER BY [Transaction].ReportDateSK
        ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING)   AS 'Running_AccountFees'
    ,[Summary].Overlimit_Balance                            AS 'Overlimit_Balance'
    ,CASE 
        WHEN SUM([Transaction].AmountChange/100.00) 
                OVER (PARTITION BY [Transaction].AccountSK
                ORDER BY [Transaction].ReportDateSK
                ROWS BETWEEN UNBOUNDED PRECEDING AND 0 PRECEDING) > [Summary].Overlimit_Balance
        THEN 1
        ELSE 0
    END                                                     AS 'Restart_Calc'
    ,''                                                     AS 'Actual_Calc'
FROM  
    Fact.[Transaction] [Transaction]
    INNER JOIN Fact.AccountSummary [Summary] ON [Summary].DateSK = [Transaction].ReportDateSK
        AND [Summary].AccountSK = [Transaction].AccountSK
        AND [Summary].[Current] = 1
WHERE IsFeeTransaction = 1
    AND [Transaction].AccountSK = 725
    AND [Transaction].ReportDateSK BETWEEN 20200217 AND 20200730

意识到你问题中的数据基本上是源数据,并且能够得出以下结论。它并不十分漂亮,但它提供了正确的输出。有关其工作原理的说明,请参见评论:

declare @t table(Tran_DateSK int, Amount decimal(10,2), Running_AccountFees int, Overlimit_Balance decimal(10,2), Restart_Calc bit, Actual_Calc decimal(10,2));
insert into @t values(20200217,39,39,3867.76,0,39),(20200217,50,89,3867.76,0,89),(20200316,39,128,4735.52,0,128),(20200316,50,178,4735.52,0,178),(20200324,50,228,2685.52,0,228),(20200330,50,278,49.52,1,49.52),(20200415,39,317,49.52,1,49.52),(20200515,39,356,3917.28,0,88.52),(20200515,50,406,3917.28,0,138.52),(20200519,50,456,3467.28,0,188.52),(20200604,50,506,3017.28,0,238.52),(20200609,50,556,2167.28,0,288.52),(20200611,50,606,49.28,1,49.28),(20200615,39,645,3917.04,0,88.28),(20200615,50,695,3917.04,0,138.28),(20200616,50,745,3017.04,0,188.28),(20200616,50,795,3017.04,0,238.28),(20200619,50,845,2567.04,0,288.28),(20200624,50,895,47.04,1,47.04),(20200715,39,934,47.04,1,47.04);

with t as
(
    select Tran_DateSK
          ,Amount
          -- Check if the Running_AccountFees are over the Overlimit_Balance
          ,case when sum(Amount) over (order by Tran_DateSK,Amount,Overlimit_Balance rows unbounded preceding) > Overlimit_Balance
                        -- If so, check if the Running_AccountFees in the previous row were also over the Overlimit_Balance
                  then case when (sum(Amount) over (order by Tran_DateSK,Amount,Overlimit_Balance rows unbounded preceding) - Amount) > lag(Overlimit_Balance,1,0) over (order by Tran_DateSK,Amount,Overlimit_Balance)
                            then 0      -- and in those instances this means multiple Restart_Calcs in a row, so set the Amount to zero as we don't want to increase the fees when calculating the Actual_Calc
                            else Amount
                            end
              else Amount
              end as Amount_Adj

          ,sum(Amount) over (order by Tran_DateSK,Amount,Overlimit_Balance rows unbounded preceding) as Running_AccountFees
          
          ,lag(Overlimit_Balance,1,0) over (order by Tran_DateSK,Amount,Overlimit_Balance) as Prev_Overlimit_Balance
          
          ,Overlimit_Balance

          ,case when sum(Amount) over (order by Tran_DateSK,Amount,Overlimit_Balance rows unbounded preceding) > Overlimit_Balance
                then 1
                else 0
                end as Restart_Calc
    from @t
)
,b as
(
    select *
          ,case when Running_AccountFees > Overlimit_Balance    -- If this row is the first in a possible series of balance resets
                    and sum(Amount_Adj) over (order by Tran_DateSK,Amount,Overlimit_Balance rows between unbounded preceding and 1 preceding) <= Prev_Overlimit_Balance
                then Overlimit_Balance      -- Take the Overlimit_Balance and subtract the *Adjusted* Running_AccountFees
                     - sum(Amount_Adj) over (order by Tran_DateSK,Amount,Overlimit_Balance rows  between unbounded preceding and 1 preceding)
                     - Amount_Adj
                else 0
                end as Reset_Bal
    from t
)
select Tran_DateSK
      ,Amount
      ,Running_AccountFees
      ,Overlimit_Balance
      ,Restart_Calc
      -- For each *Adjusted* Running_AccountFees, apply the most negative Reset_Bal value, as this will contain the entire amount that needs to be reset from the current *Adjusted* Running_AccountFees to get the correct Balance_Calc
      ,sum(Amount_Adj) over (order by Tran_DateSK,Amount,Overlimit_Balance rows unbounded preceding)
        + min(Reset_Bal) over (order by Tran_DateSK,Amount,Overlimit_Balance rows unbounded preceding)
        as Balance_Calc
from b
order by Tran_DateSK;

我的猜测是,你们需要使用这种方法。为了给您提供一个有效的解决方案,我需要一个DDL脚本和/或如Alex所说,请添加源数据以配合当前脚本和所需的输出。在不知道你的情况下很难提供帮助。回答得好,我在其中加入了一个游标循环,并保持了一个可变的运行平衡。我测试了IO/时间与你的相比,你的性能更好。不用担心。一般来说,你应该尽量不再使用光标。实际用例的数量很少。

+-------------+--------+---------------------+-------------------+--------------+--------------+
| Tran_DateSK | Amount | Running_AccountFees | Overlimit_Balance | Restart_Calc | Balance_Calc |
+-------------+--------+---------------------+-------------------+--------------+--------------+
|    20200217 |  39.00 |               39.00 |           3867.76 |            0 |        39.00 |
|    20200217 |  50.00 |               89.00 |           3867.76 |            0 |        89.00 |
|    20200316 |  39.00 |              128.00 |           4735.52 |            0 |       128.00 |
|    20200316 |  50.00 |              178.00 |           4735.52 |            0 |       178.00 |
|    20200324 |  50.00 |              228.00 |           2685.52 |            0 |       228.00 |
|    20200330 |  50.00 |              278.00 |             49.52 |            1 |        49.52 |
|    20200415 |  39.00 |              317.00 |             49.52 |            1 |        49.52 |
|    20200515 |  39.00 |              356.00 |           3917.28 |            0 |        88.52 |
|    20200515 |  50.00 |              406.00 |           3917.28 |            0 |       138.52 |
|    20200519 |  50.00 |              456.00 |           3467.28 |            0 |       188.52 |
|    20200604 |  50.00 |              506.00 |           3017.28 |            0 |       238.52 |
|    20200609 |  50.00 |              556.00 |           2167.28 |            0 |       288.52 |
|    20200611 |  50.00 |              606.00 |             49.28 |            1 |        49.28 |
|    20200615 |  39.00 |              645.00 |           3917.04 |            0 |        88.28 |
|    20200615 |  50.00 |              695.00 |           3917.04 |            0 |       138.28 |
|    20200616 |  50.00 |              745.00 |           3017.04 |            0 |       188.28 |
|    20200616 |  50.00 |              795.00 |           3017.04 |            0 |       238.28 |
|    20200619 |  50.00 |              845.00 |           2567.04 |            0 |       288.28 |
|    20200624 |  50.00 |              895.00 |             47.04 |            1 |        47.04 |
|    20200715 |  39.00 |              934.00 |             47.04 |            1 |        47.04 |
+-------------+--------+---------------------+-------------------+--------------+--------------+