【问题标题】:Calculation of Average Due Date with SQL query使用 SQL 查询计算平均到期日
【发布时间】:2020-07-25 18:27:56
【问题描述】:

我想计算每个客户的平均到期日和余额。我有两个表,第一个是客户列表表,第二个是支付交易。

表 A (lG_060_CLCARD) - 客户列表

LOGICALREF  DEFINITION_
------------------------
18166       ABC INC

表 B (LG_060_04_PAYTRANS) - 支付交易

CARDREF      PROCDATE     SIGN   TOTAL   DISCDUEDATE
-----------------------------------------------------
18166       2020.03.21     1     1000     2020.03.21
18166       2020.03.21     1     15000    2020.03.21
18166       2020.02.29     0     2500     2020.03.30
18166       2020.02.29     0     6000     2020.03.30
18166       2020.03.16     0     4000     2020.04.15
18166       2020.03.16     0     6500     2020.04.15
18166       2020.03.16     0     2000     2020.05.15

第二张表说明:该客户 (18166) 在 2020 年 3 月 21 日向我支付了两次(SIGN 表示支付给我,如果等于 1),即 1000 + 15000 = 16000。同一客户在 2 个不同的商品上购买了 5 件不同的商品天。他们的到期日期显示在DISCDUEDATE 列中。

平均到期日手动计算:

表 B (LG_060_04_PAYTRANS) - 支付交易

CARDREF      PROCDATE     SIGN   TOTAL   DISCDUEDATE   *cumulativeBalance
-------------------------------------------------------------------------
18166       2020.03.21     1     1000     2020.03.21    -1000
18166       2020.03.21     1     15000    2020.03.21    -16000
18166       2020.02.29     0     2500     2020.03.30    -13500
18166       2020.02.29     0     6000     2020.03.30    -7500
18166       2020.03.16     0     4000     2020.04.15    -3500
18166       2020.03.16     0     6500     2020.04.15    3000 --> balance turns into positive
18166       2020.03.16     0     2000     2020.05.15    

计算从第六行开始,因为这一行的余额变为正数。我们在第六行使用 3000 而不是 6500。

计算表应该是这样的:

CARDREF      PROCDATE     SIGN   TOTAL   DISCDUEDATE   DAY
-----------------------------------------------------------
18166       2020.03.16     0     3000     2020.04.15   2
18166       2020.03.16     0     2000     2020.05.15   32

DAY 表示今天和到期日DISCDUEDATE 之间的差异。今天是2020.04.13

所以,平均到期日 (ADD) 是;

2 x 3000  = 6000
32 x 2000 = 64000
          +--------
            68000

ADD = 68000 : (3000+2000) = 13,6 = 13 days

对我来说真正的问题是计算余额和日期变成正数(正余额日期和金额)。在那一天之后,所有正数行 (SIGN=0) 都应添加到计算中。

我有一些计算代码。

SELECT
    CL.DEFINITION_,
    SUM(CASE WHEN SIGN=1 THEN -1 WHEN SIGN=0 THEN 1 END * TOTAL) AS BALANCE,
    FLOOR(SUM(DUEDATE)/SUM(TOTAL)) AS 'AVG DATE',
    CONVERT(VARCHAR, DATEADD(DAY, FLOOR(SUM(DUEDATE)/SUM(TOTAL)), GETDATE()),104) AS 'AVG DUE DATE'
FROM
    LG_060_CLCARD CL
LEFT JOIN 
    (SELECT
         CARDREF, SIGN, TOTAL,
         (DATEDIFF(DAY, GETDATE(),DISCDUEDATE) * TOTAL) AS DUEDATE
     FROM
         LG_060_04_PAYTRANS
     WHERE
         CANCELLED = 0) PT ON PT.CARDREF = LOGICALREF
WHERE
    LOGICALREF = 18166
GROUP BY
    CL.DEFINITION_, CL.LOGICALREF

此代码运行良好,它正确计算了余额,但它错误地计算了平均天数和平均到期日。因为我不知道如何计算正余额日期和金额?

【问题讨论】:

    标签: sql sql-server sql-server-2008


    【解决方案1】:

    我建立了一个与您类似的名为“payt”的表,并使用 tsql 进行以下工作。我添加了一个 cardref 以确保当有更多 cardref 时代码仍然有效:

    /*
    create table payt (
          cardref int,
          procdate date,
          sign int,
          total float,
          discduedate date);
    
    
        insert into payt values (18166,'2020-03-21',1,1000,'2020-03-21'),
                                  (18166,'2020-03-21',1,15000,'2020-03-21'),
                                  (18166,'2020-02-29',0,2500,'2020-03-30'),
                                  (18166,'2020-02-29',0,6000,'2020-03-30'),
                                  (18166,'2020-03-16',0,4000,'2020-04-15'),
                                  (18166,'2020-03-16',0,6500,'2020-04-15'),
                                  (18166,'2020-03-16',0,2000,'2020-05-15'),
                                  (18164,'2020-03-16',1,600,'2020-04-16'),
                                  (18164,'2020-03-16',0,2000,'2020-05-10')
        */
        select *,
        case when sign=1 then -total else total end as num,
        row_number() over (partition by cardref order by discduedate) as r1
        into #t1
        from payt
    
        declare @c as int=(select min(cardref) from payt)
        declare @m as int=(select max(cardref) from payt)
    
    
        select *,0 as dd
        into #t2
        from payt
        where cardref<@c
    
        while @c<=@m
        begin
        declare @r as int=0
        declare @s as int=-1
    
        while @s<0
        begin
        set @r=@r+1
        set @s=(select sum(num) as num
        from #t1
        where r1<=@r
        and cardref=@c)
        end
    
        insert into #t2
        select a.cardref,a.procdate,a.sign,
        case when a.r1=@r then @s else a.num end as total,
        a.discduedate,
        datediff(day,getdate(),a.discduedate) as dd
        from #t1 a
        where a.r1>=@r
        and a.cardref=@c
    
        set @c=(select min(cardref) from payt where cardref>@c)
        end
    
        select *
        from #t2
    

    【讨论】:

    • 感谢您的回复。我有一些重要的数据,由于我的 sql 知识较少,不想冒险。您能否在不插入代码的情况下重新组织代码。只是从服务器获取信息而不发送它。
    • 我评论了你不需要的 create 语句和 insert 语句。剩下的部分应该可以工作,你只需要输入正确的表格名称而不是“party”
    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    相关资源
    最近更新 更多