Tsql 如何从月度回报计算总回报

Tsql 如何从月度回报计算总回报,tsql,ssms,recursive-query,Tsql,Ssms,Recursive Query,我有一个类似的表,它有如下所示的月度回报。 我的目标是计算10000美元的投资增长。 下面显示的投资增长列是我手动计算的。对于第一个月,10000*(1+返回/100)将是第一个值。结果值将在公式中替换为下个月的回报,依此类推 有人能帮我查询一下以实现这一点吗 多谢各位 [月度回报表-投资增长列为目标] 您可以使用递归CTE来执行此操作,该CTE在表中循环,并可以引用以前计算过的行。但请注意,由于这种逐行循环,它可能会运行得相当慢,具体取决于您的环境: declare @t table (Fun

我有一个类似的表,它有如下所示的月度回报。 我的目标是计算10000美元的投资增长。 下面显示的投资增长列是我手动计算的。对于第一个月,10000*(1+返回/100)将是第一个值。结果值将在公式中替换为下个月的回报,依此类推

有人能帮我查询一下以实现这一点吗

多谢各位

[月度回报表-投资增长列为目标]


您可以使用递归CTE来执行此操作,该CTE在表中循环,并可以引用以前计算过的行。但请注意,由于这种逐行循环,它可能会运行得相当慢,具体取决于您的环境:

declare @t table (FundName nvarchar(5),ReturnRate decimal(5,2), EndDate date);
insert into @t values('FundA',1.2,'20171231'),('FundA',-0.7,'20180131'),('FundA',1.3,'20180228'),('FundA',-2.3,'20180331'),('FundA',2.5,'20180430'),('FundA',1.9,'20180531'),('FundA',0.8,'20180630'),('FundB',1.1,'20171231'),('FundB',-0.4,'20180131'),('FundB',1.6,'20180228'),('FundB',-1.3,'20180331'),('FundB',2.0,'20180430'),('FundB',0.9,'20180531'),('FundB',0.8,'20180630');

declare @InitialInvestment int = 10000;

with rn as        -- Apply a row number to each Fund, ordered by EndDate so the first row can be used as the anchor in the Recursive CTE below.
(
    select FundName
            ,ReturnRate
            ,EndDate
            ,row_number() over (partition by FundName order by EndDate) as rn
    from @t
)
,r as
(
    select FundName        -- Select just the first rows for each fund and calculate the Investment Growth
            ,ReturnRate
            ,EndDate
            ,rn
            ,cast(@InitialInvestment * (1 + (ReturnRate/100)) as decimal(20,10)) as InvestmentGrowth
    from rn
    where rn = 1

    union all

    select r.FundName      -- Then row by row, fetch the next and calculate the Investment Growth by referencing the previous row in the dataset
            ,rn.ReturnRate
            ,rn.EndDate
            ,rn.rn
            ,cast(r.InvestmentGrowth * (1 + (rn.ReturnRate/100)) as decimal(20,10)) as InvestmentGrowth
    from r
        join rn
            on r.FundName = rn.FundName
                and r.rn = rn.rn-1
)
select FundName
    ,ReturnRate
    ,EndDate
    ,InvestmentGrowth
from r
order by FundName
        ,EndDate;
输出:

+----------+------------+------------+------------------+
| FundName | ReturnRate |  EndDate   | InvestmentGrowth |
+----------+------------+------------+------------------+
| FundA    |       1.20 | 2017-12-31 | 10120.0000000000 |
| FundA    |      -0.70 | 2018-01-31 | 10049.1600000000 |
| FundA    |       1.30 | 2018-02-28 | 10179.7990800000 |
| FundA    |      -2.30 | 2018-03-31 |  9945.6637011600 |
| FundA    |       2.50 | 2018-04-30 | 10194.3052936890 |
| FundA    |       1.90 | 2018-05-31 | 10387.9970942691 |
| FundA    |       0.80 | 2018-06-30 | 10471.1010710233 |
| FundB    |       1.10 | 2017-12-31 | 10110.0000000000 |
| FundB    |      -0.40 | 2018-01-31 | 10069.5600000000 |
| FundB    |       1.60 | 2018-02-28 | 10230.6729600000 |
| FundB    |      -1.30 | 2018-03-31 | 10097.6742115200 |
| FundB    |       2.00 | 2018-04-30 | 10299.6276957504 |
| FundB    |       0.90 | 2018-05-31 | 10392.3243450122 |
| FundB    |       0.80 | 2018-06-30 | 10475.4629397723 |
+----------+------------+------------+------------------+
您可以使用“古怪的更新”方法

一些测试数据

DECLARE @t TABLE ( [name] NVARCHAR(10), [return] DECIMAL(3,1), end_date DATE
                   , InvestmentGrowth DECIMAL(12,5) DEFAULT 0)
INSERT INTO @t
([name],[return],end_date)
VALUES
('FundA', 1.2, '20171231')
,('FundA', -0.7, '20180131')
,('FundA', 1.3, '20180228')
,('FundA', -2.3, '20180331')
投资始于10000美元

DECLARE @InvestmentAmount DECIMAL(12,5) = 10000
古怪的更新位

UPDATE @t
    SET @InvestmentAmount = InvestmentGrowth = @InvestmentAmount * (1+([T].[return]/100))
    FROM @t T;

name    return  end_date    InvestmentGrowth
FundA   1.2     2017-12-31  10120.00000
FundA   -0.7    2018-01-31  10049.16000
FundA   1.3     2018-02-28  10179.79908
FundA   -2.3    2018-03-31  9945.66370

哪一版本的sql server?请阅读以获取有关改进您的问题的一些提示。sql server 2016管理服务器无忧@SunilBabuVudimudi:)-如果这是您的问题的正确解决方案,请将其标记为这样,以方便其他具有相同问题的SO用户。