我的表格包含两条信息 BusinessDate 和 DailyPerf ,其中DailyPerf显示我正在跟踪的价格值的百分比变化。数据的前几行看起来像这样
BusinessDate DailyPerf
Jan 3, 2017 -0.0356%
Jan 4, 2017 -0.4325%
Jan 5, 2017 -0.3953%
Jan 6, 2017 -0.8469%
Jan 9, 2017 -0.5050%
我要做的是计算另一列 YearFac ,它显示我离开的初始值的当前百分比
在Excel中完成数据将如下所示:
BusinessDate DailyPerf YearFac
Jan 2, 2017 NULL 100%
Jan 3, 2017 -0.0356% 99.9644%
Jan 4, 2017 -0.4325% 99.5321%
Jan 5, 2017 -0.3953% 99.1386%
Jan 6, 2017 -0.8469% 98.2989%
Jan 9, 2017 -0.5050% 97.8025%
因此,我需要使用100%的YearFac来填充查询,然后递归计算因子。需要注意的是,日期不一定是连续的(周末或节假日没有条目) - 所以我不能认为next day = this day + 1
只是第二天是下一个更大的日期
我尝试了以下
WITH cte
AS (
SELECT cast(1 as int) RowCnt,
cast('3 jan 2017' as date) BusinessDate,
cast(1.0 as float) YearFac -- anchor member
UNION ALL
select cast(ROW_NUMBER() OVER(ORDER BY p.BusinessDate ASC) + 1 as int) as RowCnt,
p.BusinessDate, -- recursive member
cast(cte.YearFac*(1.0 + p.DailyPerc) as float) YearFac
from cte
inner join dbo.MsfsDailyPnl p
on
cte.RowCnt = ROW_NUMBER() OVER(ORDER BY p.BusinessDate ASC) + 1
where p.BusinessDate < sysutcdatetime()
)
SELECT RowCnt,BusinessDate, YearFac
FROM cte
但是,当然,这会失败,因为我无法在连接中引用行号。任何人都可以建议进行修改以使此查询起作用吗?
答案 0 :(得分:1)
使用累积总和:
select BusinessDate, DailyPerf,
1 - exp(sum(log(1 + DailyPerf)) over (order by BusinessDate desc)
from (select cast('2017-01-03' as date) as BusinessDate, cast(0 as float) as DailyPerf
union all
select BusinessDate, DailyPerf from dbo.MsfsDailyPnl
) p;
答案 1 :(得分:1)
使用窗口功能
select *, sum(DailyPerf) over (order by BusinessDate) + 100 YearFac
from (
select dateadd(day, -1, min(BusinessDate)) BusinessDate, 0 DailyPerf from data
union all
select * from data) t
<强> RESULT 强>
BusinessDate DailyPerf YearFac
-------------------------------------------
02/01/2017 00:00:00 0.0000 100.0000
03/01/2017 00:00:00 -0.0356 99.9644
04/01/2017 00:00:00 -0.4325 99.5319
05/01/2017 00:00:00 -0.3953 99.1366
06/01/2017 00:00:00 -0.8469 98.2897
09/01/2017 00:00:00 -0.5050 97.7847
答案 2 :(得分:0)
以下是您可能想要尝试的内容。我还附上了表的定义,因此你知道它的外观以及可以轻松完成任务的内容。
declare @x table(BusinessDate date, DailyPerf float)
insert into @x values
('Jan 2, 2017', NULL),
('Jan 3, 2017', -0.0356),
('Jan 4, 2017', -0.4325),
('Jan 5, 2017', -0.3953),
('Jan 6, 2017', -0.8469),
('Jan 9, 2017', -0.5050)
select *,
100 + SUM(isnull(DailyPerf,0)) over (partition by (select null) order by
BusinessDate rows between unbounded preceding and current row)
from @x