SQL 服务器:对列的每个组值求和(或求差),直到满足另一列的条件

SQL Server : summing (or difference) each group values of a column until a condition is met on another column

我对 SQL 和使用 SQL Server 2012 还很陌生。我在下面使用的数据集中有一个示例。它是银行交易和发票金额的会计数据集,具有以下值客户 ID、发票日期、VADEKONTROL 指示发票到期是否过期-未过期-不是发票,BORC 是发票金额,ALACAK 是收到的付款金额, BAKIYE 是总余额。不是发票交易是银行收据。

我想为每个客户做的是从 BAKIYE 的最后数量中减去 BORC 列中从最后一个条目开始的值,直到差异 <= 0。如果没有更多条目,它应该停止减去找到的分组客户。因此,对于 M01516,应该从 1982,40 中减去 999,59,并且由于差值不为 0,继续减去 982,81 和进一步的结果(如果有的话),直到差值 <= 0。

如果某个客户的 BAKIYE 最后一个值等于 0,也不需要减法。

基本逻辑如上:

  1. 我想 select 从 BAKIYE 中减去的条目(直到 BAKIYE 达到 0 或 selected 条目与 bakiye 的总和之差达到 0,无论哪种方式你看看。

  2. 对最有可能使用分组依据的每个客户的 selected 条目进行计数和求和。

编辑:

请记住,如果 BORC 值为 0,则交易为信用,如果 ALACAK 值为 0,则交易为债务。因此,为了从上一个开始找到当前余额,我们可能必须从 BAKIYE 中减去 BORC 和 ALACAK 值。

基本上我想要的是从最后一条记录开始的每个客户组:获取 BAKIYE 值的最后一行,从同一行的 BAKIYE 中减去 BORC+ALACAK。重复这一行,直到每个客户的 BAKIYE <= 0。有了这个,我可以 select 发票金额和发票数量来支付客户的余额。

我该如何继续解决这个问题?

如有任何帮助,我们将不胜感激。

ACCID   BDATE       VADEKONTROL     BORC    ALACAK  BAKIYE
------------------------------------------------------------
M01518  12.12.2018  expired         64,51     0,00   64,51
M01518  14.01.2019  expired         69,00     0,00  133,51
M01518  12.02.2019  not expired     69,00     0,00  202,51
M01518  18.02.2019  not invoice      0,00   203,00   -0,49
M01517  14.12.2018  expired         93,49     0,00   93,49
M01517  14.01.2019  expired         93,49     0,00  186,98
M01517  12.02.2019  not expired     93,49     0,00  280,47
M01516  25.12.2018  expired         982,81    0,00  982,81
M01516  21.01.2019  expired         999,59    0,00  1982,40
M01514  11.12.2018  expired          25,10    0,00    25,10
M01514  10.01.2019  not invoice       0,00   25,10     0,00
M01514  14.01.2019  expired          25,10    0,00    25,10
M01514  24.01.2019  not invoice       0,00   25,10     0,00
M01514  11.02.2019  not expired      25,10    0,00    25,10

使用 Dwight 代码的 edit2 输出:

ACCID   BDATE        VADEKONTROL    BORC    ALACAK  BAKIYE  BAKIYE_less_BORC
M01518  2018-12-12  Vadesi Geçmiş   64,51   0,00    64,51   0,00
M01518  2019-01-14  Vadesi Geçmiş   69,00   0,00    133,51  64,51
M01518  2019-02-12  Vadesi Gelmemiş 69,00   0,00    202,51  NULL
M01518  2019-02-18  FaturaDegil     0,00    203,00  -0,49   NULL
M01517  2018-12-14  Vadesi Geçmiş   93,49   0,00    93,49   0,00
M01517  2019-01-14  Vadesi Geçmiş   93,49   0,00    186,98  93,49
M01517  2019-02-12  Vadesi Gelmemiş 93,49   0,00    280,47  NULL
M01516  2018-12-25  Vadesi Geçmiş   982,81  0,00    982,81  0,00
M01516  2019-01-21  Vadesi Geçmiş   999,59  0,00    1982,40 982,81
M01514  2018-12-11  Vadesi Geçmiş   25,10   0,00    25,10   0,00
M01514  2019-01-10  FaturaDegil     0,00    25,10   0,00    NULL
M01514  2019-01-14  Vadesi Geçmiş   25,10   0,00    25,10   0,00
M01514  2019-01-24  FaturaDegil     0,00    25,10   0,00    NULL
M01514  2019-02-11  Vadesi Gelmemiş 25,10   0,00    25,10   NULL

我也使用了下面的代码(FNM00_ACC_CODE 是 ACCID)并且得到了几乎正确的结果。

select FNM00_ACC_CODE,borc,alacak,BAKIYE,bdate,vadekontrol,
(cast(((SELECT TOP 1 BAKIYE FROM GRID_Temp_Current_Accounts_All_Can2 ac2 
WHERE ac2.FNM00_ACC_CODE=c.FNM00_ACC_CODE ORDER BY ac2.ID desc)-
            (select ISNULL(sum(convert(decimal(18,2),BORC)),'0.00') as money 
from GRID_Temp_Current_Accounts_All_Can2 as ac
        WHERE ac.FNM00_ACC_CODE=c.FNM00_ACC_CODE
            and ac.id >= c.id)) as money)) BAKIYE2 from 
GridTelekom_MetaData.dbo.GRID_Temp_Current_Accounts_All_Can2 c




  FNM00_ACC_CODE      borc     alacak        BAKIYE    bdate    vadekontrol BAKIYE2
          M00385      2228,75   0,00     7689,75    2018-11-19  Vadesi Geçmiş   -7039,00
          M00385      2545,34   0,00     10235,09   2018-11-29  Vadesi Geçmiş   -4810,25
          M00385      2256,00   0,00     12491,09   2018-12-18  Vadesi Geçmiş   -2264,91
          M00385      0,00     3000,00   9491,09    2018-12-20  FaturaDegil -8,91
          M00385      0,00     3500,00   5991,09    2018-12-28  FaturaDegil -8,91
          M00385      2969,42   0,00     8960,51    2018-12-31  Vadesi Geçmiş   -8,91
          M00385      2244,15   0,00     11204,66   2019-01-18  Vadesi Geçmiş   2960,51  
          M00385      0,00     6000,00   5204,66    2019-01-24  FaturaDegil 5204,66
          M00385      2237,34   0,00     7442,00    2019-01-29  Vadesi Geçmiş   5204,66
          M00385      2217,11   0,00     9659,11    2019-02-18  Vadesi Gelmemiş 7442,00

每当 BAKIYE2 达到负值时,我都希望交易达到那个点。因此,对于上面的示例,我需要最后 5 行,因为最后 5 行的 BORC 总和等于 9668.02,比我 9659.11 的最后一个当前 BAKIYE 多 8.91。然后我可以区分过期和未过期的到期日。

使用这种方法,虽然我正在考虑 selecting 所有 BAKIYE2 >= 0 的条目,但是这将跳过最后一行,它将 BAKIYE 带入负数(在这种情况下它不会 select 2969.42).

我已更改查询以提供 1 个新列和对先前提供的原始计算列的更改。

我还翻译了一些列名称,以便于我使用它们(如果给您带来不便,我深表歉意)。

此查询现在通过从当时的余额 (bakiye) 中减去债务总和 (borc) 来显示余额何时达到 0。它还会显示任何到期发票是否有未付余额,包括任何贷项 (alacak)。这是使用您使用过的相关内联子查询完成的,但是使用 bdate 而不是 accid 来建立最新余额并在达到 0 或更少之前查询记录,而不是在达到 0 或更少之后查询记录,这就是您的版本中发生的情况查询。

我希望这有用,如果我们更接近或是否需要进一步调整,请告诉我。

declare @t table (
ACCID nvarchar(10),
BDATE date,
MaturityControl nvarchar(15),
Debt float,
Credit float,
Balance float
);

insert into @t (ACCID, BDATE, MaturityControl, Debt, Credit, Balance)
values
('M01518',  '2018-12-12',  'expired',         64.51,     0.00,   64.51),
('M01518',  '2019-01-14',  'expired',         69.00,     0.00,  133.51),
('M01518',  '2019-02-12',  'not expired',     69.00,     0.00,  202.51),
('M01518',  '2019-02-18',  'not invoice',      0.00,   203.00,   -0.49),
('M01517',  '2018-12-14',  'expired',         93.49,     0.00,   93.49),
('M01517',  '2019-01-14',  'expired',         93.49,     0.00,  186.98),
('M01517',  '2019-02-12',  'not expired',     93.49,     0.00,  280.47),
('M01516',  '2018-12-25',  'expired',         982.81,    0.00,  982.81),
('M01516',  '2019-01-21',  'expired',         999.59,    0.00,  1982.40),
('M01514',  '2018-12-11',  'expired',          25.10,    0.00,    25.10),
('M01514',  '2019-01-10',  'not invoice',       0.00,   25.10,     0.00),
('M01514',  '2019-01-14',  'expired',          25.10,    0.00,    25.10),
('M01514',  '2019-01-24',  'not invoice',       0.00,   25.10,     0.00),
('M01514', ' 2019-02-11',  'not expired',      25.10,    0.00,    25.10),
('M00385',  '2018-11-19', 'expired',           2228.75, 0.00, 7689.75),
('M00385', '2018-11-29', 'expired',            2545.34, 0.00, 10235.09),
('M00385', '2018-12-18', 'expired',            2256.00, 0.00, 12491.09),
('M00385', ' 2018-12-20', 'not invoice',       0.00, 3000.00, 9491.09),
('M00385', '2018-12-28', 'not invoice',        0.00, 3500.00, 5991.09),
('M00385', '2018-12-31', 'expired',            2969.42, 0.00, 8960.51),
('M00385', '2019-01-18', 'expired',            2244.15, 0.00, 11204.66),
('M00385', '2019-01-24', 'not invoice',        0.00, 6000.00, 5204.66),
('M00385', '2019-01-29', 'expired',            2237.34, 0.00, 7442.00),
('M00385', '2019-02-18', 'not expired',        2217.11, 0.00, 9659.11);

select t.ACCID, t.BDATE, MaturityControl, Debt, Credit, Balance, 
case when Balance_Less_Debt is null then balance-debt else Balance_Less_Debt end as computed_difference_in_transactions,
(select((select top 1 Balance from @t as t4 where t.accid=t4.ACCID order by t4.BDATE desc)-
(select sum(Debt) from @t as t3 where t.ACCID=t3.ACCID and t.BDATE>=t3.BDATE))-
(select sum(Credit) from @t as t5 where t.ACCID=t5.ACCID and t.BDATE>=t5.BDATE)) as current_balance_less_summed_debt
from @t as t
outer apply (select ACCID, BDATE, Balance-Debt as Balance_Less_Debt from @t t2 where 
t.ACCID=t2.ACCID and t.BDATE=t2.BDATE and MaturityControl='expired'
group by ACCID, BDATE, Balance, Debt
having balance-Debt <=0
) 
agg 
where MaturityControl = 'expired'
order by t.ACCID desc, t.BDATE;