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

问题描述 投票:0回答:1

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

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

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

基本逻辑在上面并且具有:

  1. 我想选择从BAKIYE中减去的条目(直到BAKIYE达到0或所选条目之和与bakiye之间的差值达到0,无论你怎样看待它。
  2. 对每个最有可能使用group by的客户计算并汇总所选条目。

编辑:

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

基本上我想要的是从最后一条记录开始的每个客户组:获取BAKIYE值的最后一行,从BAKIYE减去同一行的BORC + ALACAK。重复此操作,直到每个客户的BAKIYE <= 0。有了这个,我可以选择发票金额和发票数量,这些发票将涵盖客户的剩余余额。

我怎样才能继续解决这个问题?

任何帮助将不胜感激。

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的代码编辑2输出:

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,比最后一个当前的BAKIYE(9659.11)多8.91。然后,我可以区分过期到期日和过期到期日。

虽然我想用这种方法选择BAKIYE2> = 0的所有条目,但是这会跳过BAKIYE进入最后一行的最后一行(在这种情况下它不会选择2969.42)。

sql-server group-by sql-server-2012 subquery window-functions
1个回答
0
投票

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

我还翻译了一些列名,以便我更容易使用(如果这给您带来不便,我很抱歉)。

此查询现在通过将债务(borc)的总和从当时的余额(bakiye)中取出来显示余额达到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;
© www.soinside.com 2019 - 2024. All rights reserved.