SQL:在Debits(账单)中有效地应用Credits(支付)

时间:2011-12-16 14:11:34

标签: sql oracle reporting finance

我正试图从现成的金融系统中产生一个“现金滞后”报告。我可以访问数据库(Oracle)。报告应将贷记应用于最早的借方,并计算生成账单与收到付款之间的天数差异。所有借方和贷方都存储在金融交易表的单个列中。适用的专栏是:

Column Name  Type
-----------  -------------
AMOUNT       NUMERIC(15,2)   --debits are positive, credits are negative
FT_ID        CHAR(10)
ACCOUNT_ID   CHAR(10)
ACCEPTED_DT  DATETIME

所以对于像这样的表:

ACCOUNT_ID  FT_ID  AMOUNT   ACCEPTED_DT
---------------------------------------
         1  12345  100.00   12/01/2011
         1  12346  -75.00   12/11/2011
         1  12347  100.00   12/12/2011
         1  12348  -50.00   12/16/2011

我想要取回的内容如下所示(编辑:更新以显示已应用的金额。我想要实际的信用额度,但可以根据信用卡的FT ID查找):

ACCOUNT_ID  DEBIT_ID  DEBIT_AMOUNT  CREDIT_ID  CREDIT_AMOUNT  AGE
------------------------------------------------------------------
         1     12345         75.00      12346         -75.00   10
         1     12345         25.00      12348         -25.00   15
         1     12347         25.00      12348         -25.00    4
         1     12347         75.00      NULL            NULL  NULL

编辑:我公司选择的现成系统之美是支付应用程序是可配置的,这意味着信用卡与借记卡没有直接联系。我们首先将资金用于最早的债务,这是我试图在示例中显示的内容。第一笔付款完全适用于最早的债务。第二笔付款分为最老和第二老债务。这一直持续到所有学分都被应用为止。

编辑2 :对不起这对我来说似乎很难解释:)看看示例数据,FT 12346完全适用于FT 12345,在账户上留下了25美元的债务。然后,下一笔付款也将适用于此债务,任何剩余金额将应用于下一个最老的债务。跑步总数与我想要完成的完全不符,因为我需要知道比赛的每个“切片”的年龄:

编辑3 :上面的表格根本不清楚,抱歉。我已经更新了表格。

                 Debits                 Credits
        +-----------------------+-------------------------+
        |     FT 12345          |      FT 12346           |
        |                       |                         |
        |     $100.00           |       $75.00            |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       +-------------------------+
        |                       |      FT 12348           |
        |                       |       $50.00            |
        |                       |                         +----->$25.00 towards 12345
        +-----------------------|.........................|
        |    FT 12347           |                         |
        |                       |                         +----->$25.00 towards 12347
        |      $100.00          +-------------------------+
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        |                       |                         |
        +-----------------------+-------------------------+

我们有一个使用游标的解决方案,但是在整个金融交易表(约50米行)中,这非常慢。我想知道是否有办法在纯表格中重述问题以加快速度。我发现a recipe for genreating a running balance似乎是一个开始,但我不确定从那里开始。

1 个答案:

答案 0 :(得分:1)

如果能够正确理解您的需求,可以使用分析来实现:

create table cred_deb (account_id integer, transaction_date date, amount number);


insert into cred_deb values (1, sysdate - 10, 100.00); -- bill of 100
insert into cred_deb values (1, sysdate - 9, -10.00); -- payment of 10
insert into cred_deb values (1, sysdate - 8, -80.00); -- payment of 80
insert into cred_deb values (1, sysdate - 5, 80.00); -- bill of 80
insert into cred_deb values(1, sysdate - 3, -80.00); -- payment of 80

-- 2nd account
insert into cred_deb values(2, sysdate - 3, 80.00); -- bill of 80
insert into cred_deb values(2, sysdate - 3, -80.00); -- payment of 80



select account_id, 
       transaction_date,
       amount,
       sum(amount) over( partition by account_id order by transaction_date) running_total
from cred_deb
order by account_id, transaction_date;

ACCOUNT_ID             TRANSACTION_DATE          AMOUNT                 RUNNING_TOTAL          
---------------------- ------------------------- ---------------------- ---------------------- 
1                      06-DEC-11                 100                    100                    
1                      07-DEC-11                 -10                    90                     
1                      08-DEC-11                 -80                    10                     
1                      11-DEC-11                 80                     90                     
1                      13-DEC-11                 -80                    10                     
2                      13-DEC-11                 80                     80                     
2                      13-DEC-11                 -80                    0                     

仔细观察您的示例,也许您希望将特定帐单的所有信用额与帐单金额分组到一行。如果您能够更清楚地描述您的内容,我认为分析将能够解决它。

编辑 - 增加了几天的年龄。

select account_id, 
       transaction_date,
       amount,
       sum(amount) over( partition by account_id order by transaction_date) running_total,
       trunc(transaction_date) - max(case 
                                      when amount > 0 then 
                                        trunc(transaction_date)
                                      else
                                        null
                                      end) over (partition by account_id order by transaction_date)  age_in_days
from cred_deb
order by account_id, transaction_date