用SQL计算每月付款的利率

时间:2018-12-04 15:04:03

标签: oracle oracle12c finance

是否有一种方法可以在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()

1 个答案:

答案 0 :(得分:3)

正如我在您的帖子下方的评论中所说:您所寻找的被称为“内部收益率”。实际上,您正在寻找一种非常特殊的情况-分期偿还的贷款,定期还款。 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。然后我从其他值计算利率。

该功能要求本金和每月付款,两者均为NOT NULL且假定为正。还需要术语(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%