次のようなデータテーブルがあります。
Group ID M0 M1 ... M20
------------------------------------
1 1 10 -2 ... 54
1 2 -8 10 ... -20
2 6 -10 12 ... 0
2 4 45 52 ... 0
2 5 12 102 ... 0
次のように、グループごとにデータをグループ化しています。
SELECT Group
, round(sum(M0+M1+M2+...+M20)/count(ID),2) as profit
, round(sum(M0),2) as M0
, round(sum(M1),2) as M1
, ...
, round(sum(M20),2) as M20
FROM
data_table
GROUP BY
Group
追加する必要があるのは、M0 から M20 の列に基づく IRR です。
次のような IRR 関数を見つけました。
CREATE FUNCTION [dbo].[ufn_IRR]
(
@strIDs VARCHAR(8000),
@guess DECIMAL(30,10)
)
RETURNS DECIMAL(30, 10)
AS
BEGIN
DECLARE @t_IDs TABLE (
id INT IDENTITY(0, 1),
value DECIMAL(30, 10)
)
DECLARE @strID VARCHAR(12),@sepPos INT,@NPV DECIMAL(30, 10)
SET @strIDs = COALESCE(@strIDs + ',', '')
SET @sepPos = CHARINDEX(',', @strIDs)
WHILE @sepPos > 0
BEGIN
SET @strID = LEFT(@strIDs, @sepPos - 1)
INSERT INTO @t_IDs ( value ) SELECT ( CAST(@strID AS DECIMAL(20, 10)) ) WHERE ISNUMERIC(@strID) = 1
SET @strIDs = RIGHT(@strIDs, DATALENGTH(@strIDs) - @sepPos)
SET @sepPos = CHARINDEX(',', @strIDs)
END
SET @guess = CASE WHEN ISNULL(@guess, 0) <= 0 THEN 0.00001 ELSE @guess END
SELECT @NPV = SUM(value / POWER(1 + @guess, id)) FROM @t_IDs
WHILE @NPV > 0
BEGIN
SET @guess = @guess + 0.00001
SELECT @NPV = SUM(value / POWER(1 + @guess, id)) FROM @t_IDs
END
RETURN @guess
END
使用例は次のようになります。
SELECT dbo.ufn_IRR('-4000,1200,1410,1875,1050',0.00001)
しかし、私の場合、次のように、列から文字列を作成することを避けたいと思います:
SELECT dbo.ufn_IRR(
cast(round(sum([M0]), 2) AS NVARCHAR)+','
+cast(round(sum([M1]), 2) AS NVARCHAR)+','
+cast(round(sum([M2]), 2) AS NVARCHAR)+','
+cast(round(sum([M3]), 2) AS NVARCHAR)+','
+cast(round(sum([M4]), 2) AS NVARCHAR)+','
+...+','
+cast(round(sum([M20]), 2) AS NVARCHAR)
,0.00001)
最初に文字列を作成してから、関数内でそれをテーブルにカットするのは無意味だと思います。
列を渡すことができるように IRR 関数を変更したいのですが、それを行う方法がわかりません:/