oracle - 在 SQL 中从每月付款计算利率
问题描述
有没有办法在 SQL (Oracle) 中知道贷款金额、每月付款和期限来计算利率?我可以在知道利率的情况下轻松计算付款,但是相反的方法似乎要困难得多。
每月还款计算(利率 = 0.1 (10%),贷款规模 = 1000,期限 = 24):
select (0.1/12 * 1000) / (1 - power(1 + 0.1/12, -24)) as mpayment
from dual;
46.1449263375165
问题是如何从每月支付 46.14 美元、贷款规模 1,000 美元、期限 24 个月并计算 10% 作为利率。
例如,在 MS Excel 中,要使用的函数是RATE()
解决方案
正如我在您帖子下方的评论中所说:您正在寻找的东西被称为“内部收益率”。实际上,您正在寻找一种非常特殊的情况 - 定期还款的摊销贷款。Oracle 在附加包中提供了 IRR 功能;如果您只想使用基本 SQL 和 PL/SQL,则必须使用 UDF(用户定义函数)。
这是一种使用牛顿法对其进行编码的方法。我同时演示了几件事。注意数字数据类型(特定于 PL/SQL,不能在普通 SQL 中使用;但是,运行时会将输入从 NUMBER 转换为 PL/SQL 数据类型,并将返回值转换回 NUMBER,透明)。在代码中使用这些数据类型可以使函数更快 - 特别是如果您使用本机编译(正如我在下面的第一行代码中所示)。
到目前为止,一切都应该在旧版本的 PL/SQL 中工作。仅从 12.1 版开始,并且仅当您主要从 SQL 调用该函数时,您才可以使用pragma udf
声明 - 这将加速调用该函数的纯 SQL 代码。
该函数返回一个“年化”抵押贷款利率(它计算月利率,然后简单地乘以 12 - 没有复利 - 因为这就是抵押贷款利率的工作方式,至少在美国是这样)。比率以十进制数返回,而不是乘以 100;也就是说,不是百分比。如果函数返回的利率为 0.038,则意味着 3.8%(每年的抵押贷款利率)。在最后的简短演示中,我应该如何将函数调用包装在其他 SQL 代码中以美化答案。
对于最后的例子,我取了200,000的本金,以6.5%的利率计算了30年(360个月)的月供;我每月支付 1,264.14。然后我根据其他值计算利率。
该函数需要本金和每月付款,两者均非空且假定为正数。术语(IN MONTHS)也是需要的,但我编码了一个默认值 360。(也许最好不要为此编码默认值并将其设为必需。)您可以选择输入所需的精度;我默认编码了非常高的精度,因为无论如何计算都非常快。
我没有编写任何类型的错误处理代码;显然,如果您选择将此功能(或任何类似功能)用于培训/学习以外的任何目的,则必须这样做。
alter session set plsql_code_type = native;
create or replace function mortgage_rate(
p_principal simple_double
, p_monthly_payment simple_double
, p_term simple_integer default 360
, p_precision simple_double default 0.00000001
)
return number
as
pragma udf; -- Comment out this line if Oracle version is < 12.1
z simple_double := p_monthly_payment/p_principal;
u simple_double := 1 / (p_term * z);
v simple_double := 0;
delta simple_double := 0;
begin
for i in 1 .. 100 loop
v := power(u, p_term);
delta := ( z * u * ( v - 1) - u + 1 ) / ( z * (p_term + 1) * v - z - 1 );
u := u - delta;
exit when abs(delta) < p_precision;
end loop;
return 12 * (1/u - 1);
end;
/
select to_char( 100 * mortgage_rate(200000, 1264.14, 360), 'fm990.000')
|| '%' as interest_rate
from dual;
INTEREST_RATE
----------------
6.500%
推荐阅读
- performance - Mezzanine CMS 中的慢速搜索
- shell - 如何按字母顺序对第二列进行排序,然后在 shell 脚本中按数字排序?
- jboss-eap-7 - 如何配置应用程序以在 JBOSS 上运行两个不同的端口
- javascript - 如何检查 Discord.js 雪花是否包含在其他 ID 数组中
- elasticsearch - 与弹性搜索中的 IN 运算符完全匹配
- mongodb - 在 mongodb 中加入两个具有选定字段和 where 子句的表
- node.js - 加入和离开聊天的正确 http 方法是什么
- scikit-learn - 结合两种机器学习算法以实现更高的预测准确性
- excel - INDEX 组合两列,其中一列跨越多行
- c# - 如何在检查员的脚本上设置预制子组件?