我正在尝试根据以下公式计算出一个SQL查询来计算未来贷款余额:
FV (未来余额)= 简历(当前余额) - P (修复还款)+ 我 (利息资本化)
其中**我 =( CV * APR (年度百分比率) / 365 * D (期间之间的天数))
以下是原始数据示例:
Account ID Principal P (Payment) APR
123 $10,000.00 $200.00 0.2
以下是示例输出:
Term Account ID CV (Current Balance) P (Payment) APR D (Days) I (Interest Cap) FV (Future Balance)
1 123 $10,000.00 $200.00 0.2 31 169.86 $9,969.86
2 123 $9,969.86 $200.00 0.2 30 163.89 $9,933.75
3 123 $9,933.75 $200.00 0.2 31 168.74 $9,902.49
4 123 $9,902.49 $200.00 0.2 30 162.78 $9,865.27
.....
N 123 <Term N-1 FV> $200.00 0.2 30 Derived Interest Derived FV
CV的值始终是前一个词的FV(FV是根据公式计算的)
我当前的约束是我没有足够的权限在我的SQL环境中创建过程或函数
在 Excel 上似乎是一个简单的练习,但是如果不使用过程/函数,我无法弄清楚如何在SQL中执行....
答案 0 :(得分:3)
如果您使用的是Oracle 11gR2,则可以使用递归CTE。
create table mytable(
account_id number,
principal number,
payment number,
apr number
);
insert into mytable values(123, 10000, 200, 0.2);
insert into mytable values(124, 7000, 180, 0.22);
with x(term, account_id, current_balance, payment, apr, days, interest, future_balance) as (
select 1,
account_id,
principal,
payment,
apr,
extract(day from last_day(sysdate)),
principal * apr * extract(day from last_day(sysdate)) / 365,
(principal * apr * extract(day from last_day(sysdate)) / 365) + principal - payment
from mytable
union all
select term + 1,
account_id,
future_balance,
payment,
apr,
extract(day from last_day(add_months(sysdate, term))),
future_balance * apr * extract(day from last_day(add_months(sysdate, term))) / 365,
(future_balance * apr * extract(day from last_day(add_months(sysdate, term))) / 365) + future_balance - payment
from x
where term <= 5
)
select * from x
order by 2,1
<强> Results 强>:
| TERM | ACCOUNT_ID | CURRENT_BALANCE | PAYMENT | APR | DAYS | INTEREST | FUTURE_BALANCE |
|------|------------|-------------------|---------|------|------|------------------|-------------------|
| 1 | 123 | 10000 | 200 | 0.2 | 31 | 169.86301369863 | 9969.86301369863 |
| 2 | 123 | 9969.86301369863 | 200 | 0.2 | 30 | 163.888159129293 | 9933.751172827922 |
| 3 | 123 | 9933.751172827922 | 200 | 0.2 | 31 | 168.737691154885 | 9902.488863982808 |
| 4 | 123 | 9902.488863982808 | 200 | 0.2 | 30 | 162.780638859991 | 9865.269502842799 |
| 5 | 123 | 9865.269502842799 | 200 | 0.2 | 31 | 167.574440870206 | 9832.843943713006 |
| 6 | 123 | 9832.843943713006 | 200 | 0.2 | 31 | 167.023650550741 | 9799.867594263747 |
| 1 | 124 | 7000 | 180 | 0.22 | 31 | 130.794520547945 | 6950.794520547946 |
| 2 | 124 | 6950.794520547946 | 180 | 0.22 | 30 | 125.685599549634 | 6896.480120097579 |
| 3 | 124 | 6896.480120097579 | 180 | 0.22 | 31 | 128.860258682371 | 6845.340378779951 |
| 4 | 124 | 6845.340378779951 | 180 | 0.22 | 30 | 123.778757534103 | 6789.119136314053 |
| 5 | 124 | 6789.119136314053 | 180 | 0.22 | 31 | 126.854226053868 | 6735.973362367922 |
| 6 | 124 | 6735.973362367922 | 180 | 0.22 | 31 | 125.861200907806 | 6681.834563275728 |
UNION查询的第一部分选择表中的数据,将术语编号指定为1,计算当月的天数,计算利息和未来余额。
查询的第二部分基于前一步骤的计算结果迭代地计算同一组数据。只要满足where clause
,您就可以继续这样做,您可以使用该术语来限制术语数量。
答案 1 :(得分:2)
另一种方法是使用MODEL子句。
WITH x (term, account_id, current_balance, payment, apr, days, interest, future_balance)
AS (SELECT 1,
account_id,
principal,
payment,
apr,
EXTRACT (DAY FROM LAST_DAY (SYSDATE)),
principal * apr * EXTRACT (DAY FROM LAST_DAY (SYSDATE)) / 365,
( principal * apr * EXTRACT (DAY FROM LAST_DAY (SYSDATE)) / 365)
+ principal
- payment
FROM mytable)
SELECT *
FROM x
MODEL
PARTITION BY (account_id)
DIMENSION BY (term)
MEASURES (current_balance, payment, apr, days, interest, future_balance)
RULES
ITERATE (4) --number of terms to be generated
(current_balance [FOR term FROM 2 TO 5 INCREMENT 1] = future_balance[CV (term) - 1], --range of terms to generated
payment [term] = payment[1],
apr [term] = apr[1],
days [term] = EXTRACT (DAY FROM LAST_DAY (ADD_MONTHS (SYSDATE, CV (term) - 1))),
interest [term] =
current_balance[CV (term)] * apr[CV (term)] * days[CV (term)] / 365,
future_balance [term] = interest[CV (term)] - payment[CV (term)] + current_balance[CV (term)])
<强> Results 强>:
| ACCOUNT_ID | TERM | CURRENT_BALANCE | PAYMENT | APR | DAYS | INTEREST | FUTURE_BALANCE |
|------------|------|-------------------|---------|------|------|------------------|-------------------|
| 123 | 1 | 10000 | 200 | 0.2 | 31 | 169.86301369863 | 9969.86301369863 |
| 123 | 2 | 9969.86301369863 | 200 | 0.2 | 30 | 163.888159129293 | 9933.751172827922 |
| 123 | 3 | 9933.751172827922 | 200 | 0.2 | 31 | 168.737691154885 | 9902.488863982808 |
| 123 | 4 | 9902.488863982808 | 200 | 0.2 | 30 | 162.780638859991 | 9865.269502842799 |
| 123 | 5 | 9865.269502842799 | 200 | 0.2 | 31 | 167.574440870206 | 9832.843943713006 |
| 124 | 1 | 7000 | 180 | 0.22 | 31 | 130.794520547945 | 6950.794520547946 |
| 124 | 2 | 6950.794520547946 | 180 | 0.22 | 30 | 125.685599549634 | 6896.480120097579 |
| 124 | 3 | 6896.480120097579 | 180 | 0.22 | 31 | 128.860258682371 | 6845.340378779951 |
| 124 | 4 | 6845.340378779951 | 180 | 0.22 | 30 | 123.778757534103 | 6789.119136314053 |
| 124 | 5 | 6789.119136314053 | 180 | 0.22 | 31 | 126.854226053868 | 6735.973362367922 |
一开始可能看起来令人生畏,但我使用了与递归cte完全相同的计算。如果您浏览White paper,您将更好地理解每个条款。
此外,这也适用于早期版本的Oracle。