Sql IRR函数也返回负值

Sql IRR函数也返回负值,sql,sql-server,excel,irr,Sql,Sql Server,Excel,Irr,在Excel中返回时应返回-0.98。我自己设法找到了解决方案,您可以使用-0.99初始化@guess。上面的原始示例适用于正数,但不适用于负数。该问题与功率增加1有关,因此在循环中始终为正。我扩展了上面的解决方案,它同时满足正数和负数 注意:在ELSE块1中,您必须将值从1中减去,然后转换为负数 select [dbo].[fn_IRR]('-45000,15000,20000,25000.00,10000.00,5000',0.00000000001) as IRR should retur

在Excel中返回时应返回-0.98。我自己设法找到了解决方案,您可以使用-0.99初始化@guess。上面的原始示例适用于正数,但不适用于负数。该问题与功率增加1有关,因此在循环中始终为正。我扩展了上面的解决方案,它同时满足正数和负数

注意:在ELSE块1中,您必须将值从1中减去,然后转换为负数

select [dbo].[fn_IRR]('-45000,15000,20000,25000.00,10000.00,5000',0.00000000001) as IRR should return 0.2299339513




select [dbo].[fn_IRR]('-170000,32000,35000,33000.00,29000.00,36000',0.00000000001) as IRR
( @str varchar(最大值), @精度十进制(30,10) ) 返回十进制数(30,10) 作为 开始 声明@AdjValue十进制(30,10) ,@猜测小数(30,10) ,@guess_新小数(30,10)

选择@AdjValue=0.1,@guess=0
声明@t_id表(
id INT标识(0,1),
十进制值(30,10)
)
声明净现值小数(30,10)
,@iter\u cnt int
插入@t_id
从dbo.fn_SplitString(@str,,')中选择*
当ISNULL(@guess,0)0时设置@guess=CASE
开始
WHILE(@NPV>0或@AdjValue>@precision)和(isnull(@iter\u cnt,0)<8192))
开始
设置@guess_new=@guess+@AdjValue
从@t_id中选择@NPV=SUM(值/功率(1+@guess_new,id))
设置@iter\u cnt=isnull(@iter\u cnt,0)+1
如果(@NPV>0)
选择@guess=@guess\u new
其他的
选择@AdjValue=@AdjValue/10
结束
结束
其他的
开始
WHILE(@NPV>0或@AdjValue>@precision)和(isnull(@iter\u cnt,0)<8192))
开始
设置@guess_new=@guess+@AdjValue
从@t\u id中选择@NPV=SUM(值/功率(@guess\u new,id))
设置@iter\u cnt=isnull(@iter\u cnt,0)+1
如果(@NPV>0)
选择@guess=@guess\u new
其他的
选择@AdjValue=@AdjValue/10
结束
设置@guess=1-@guess
设置@guess=-@guess
结束
返回@guess
结束

select [dbo].[fn_IRR]('-45000,15000,20000,25000.00,10000.00,5000',0.00000000001) as IRR should return 0.2299339513




select [dbo].[fn_IRR]('-170000,32000,35000,33000.00,29000.00,36000',0.00000000001) as IRR
ALTER FUNCTION [dbo].[fn_IRR]
Select @AdjValue = 0.1, @guess=0

DECLARE @t_IDs TABLE (
    id INT IDENTITY(0, 1),
    value DECIMAL(30, 10)
)
Declare @NPV DECIMAL(30, 10)
       ,@iter_cnt int

INSERT INTO @t_IDs 
    select * from dbo.fn_SplitString(@str,',')

SET @guess = CASE WHEN ISNULL(@guess, 0) <= 0 THEN 0 ELSE @guess END

SELECT @NPV = SUM(value / POWER(1 + @guess, id)) FROM @t_IDs

IF @NPV > 0
    BEGIN
        WHILE ((@NPV > 0 or @AdjValue > @precision) and (isnull(@iter_cnt,0) < 8192))
        BEGIN
            SET @guess_new = @guess + @AdjValue
            SELECT @NPV = SUM(value / POWER(1 + @guess_new, id)) FROM @t_IDs
            set @iter_cnt = isnull(@iter_cnt,0) + 1
            if (@NPV > 0)
                select @guess=@guess_new
            else
                select @AdjValue=@AdjValue/10
        END
    END
ELSE
    BEGIN
        WHILE ((@NPV > 0 or @AdjValue > @precision) and (isnull(@iter_cnt,0) < 8192))
            BEGIN
                SET @guess_new = @guess + @AdjValue
                SELECT @NPV = SUM(value / POWER(@guess_new, id)) FROM @t_IDs
                set @iter_cnt = isnull(@iter_cnt,0) + 1
                if (@NPV > 0)
                    select @guess=@guess_new
                else
                    select @AdjValue=@AdjValue/10
            END

        SET @guess = 1 - @guess
        SET @guess = -@guess
    END

RETURN @guess