在 SQL 服务器中使用 CTE 递归

Using recursion with a CTE in SQL Server

我有以下 table 结构:(这只是我最终输出查询中具有完全相同列的示例集)

实际数据在索引中的行数要多得多,在到达索引值之前我必须删除几个符号。这是为内部使用而构建的自定义索引。

https://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=b1d5ed7db79c665d8cc179ae4cc7d4f1

这是 link 到 fiddle 的 SQL 数据 下面是相同的图像:

我想计算积分对指数值的贡献,最后计算指数值。

要计算每个符号的 pts 贡献,公式为:

ptsC = yesterday_index * wt * px_change / yest_close

我没有昨天指数的起始值,即 2021 年 11 月 17 日的起始值,应视为 1000

11 月 18 日的指数值将是 1000 + sum(ptsC) 该值现在应该用于计算 11 月 22 日等每个交易品种的 ptsC...

我正在尝试编写递归 CTE,但不确定哪里出错了。

Yesterday Index 值应递归确定,因此应计算 ptsC。 最终输出应该是:

其中总点数贡献是当天所有 ptsC 的总和,新指数值是 yesterday Index Value + Total Point Contribution

下面是我生成第一个 table:

的代码
declare @beginval as float=17671.65
set @beginval=1000
declare @indexname varchar(20)='NIFTY ENERGY'
declare @mindt as datetime
select @mindt=min(datetime) from indices_json where indexname=@indexname

;
with tbl as (
SELECT        IndexName, datetime, sum(Indexmcap_today) totalMcap_today,sum(Indexmcap_yst) totalmcap_yst
FROM            indices_json
WHERE        IndexName = @indexname
group by indexname,datetime
)
,tbl2 as
(
select j.indexname,j.datetime,symbol,Indexmcap_today/d.totalMcap_today*100 calc_wt_today,Indexmcap_yst/d.totalmcap_yst*100 calc_wt_yest,iislPtsChange,adjustedClosePrice,pointchange
from indices_json j inner join tbl d on d.datetime=j.datetime and d.IndexName=j.IndexName
)
,tbl3 as
(
select indexname,datetime,symbol,calc_wt_today,calc_wt_yest,iislPtsChange,adjustedClosePrice,pointchange
,case when datetime=@mindt then @beginval*calc_wt_yest*iislPtsChange/adjustedClosePrice/100 else null end ptsC
 from tbl2 
)
,tbl4 as
(
select indexname,datetime,sum(ptsC) + @beginval NewIndexVal,sum(pointchange) PTSCC 
from tbl3
group by indexname,datetime
)
,tbl5 as
(
select *,lag(datetime,1,null) over(order by datetime asc) yest_dt 
from tbl4 
)
,
tbl6 as 
(
select d.*,s.yest_dt 
from tbl2 d inner join tbl5 s on d.datetime=s.datetime
)
,tbl7 as
(
select d.IndexName,d.datetime,d.symbol,d.calc_wt_today,d.calc_wt_yest,d.iislPtsChange,d.adjustedClosePrice,d.pointchange,case when i.datetime is null then @beginval else i.NewIndexVal end yest_index 
from tbl6 d left join tbl4 i on d.yest_dt=i.datetime
)
select IndexName,convert(varchar(12),datetime,106)date,symbol,round(calc_wt_yest,4) wt,iislPtsChange px_change,adjustedClosePrice yest_close--,pointchange,yest_index
from tbl7 d where datetime <='2021-11-24'
order by datetime

提前致谢。

我找到了一个解决方案: 我为每个日期的每个成分计算了 returns 然后将这些 returns 总结为一个日期 然后乘以所有日期的 returns 的所有总和以得出最终值 - 这有效 下面是相同的查询。我这里不需要递归

declare @beginval as float=17671.65

declare @indexname varchar(20)='NIFTY 50'
declare @mindt as datetime
select @mindt=min(datetime) from indices_json where indexname=@indexname
declare @startdt as datetime = '2021-11-01'
;
with tbl as (
SELECT        IndexName, datetime, sum(Indexmcap_today) totalMcap_today,sum(Indexmcap_yst) totalmcap_yst
FROM            indices_json
WHERE        IndexName = @indexname-- and symbol!='AXISBANK'
group by indexname,datetime
)
,tbl2 as
(
select j.indexname,j.datetime,symbol,Indexmcap_today/d.totalMcap_today*100 calc_wt_today,Indexmcap_yst/d.totalmcap_yst*100 calc_wt_yest,iislPtsChange,adjustedClosePrice,pointchange
from indices_json j inner join tbl d on d.datetime=j.datetime and d.IndexName=j.IndexName
)
,tbl7 as
(
select d.IndexName,d.datetime,d.symbol,d.calc_wt_today,d.calc_wt_yest,d.iislPtsChange,d.adjustedClosePrice,d.pointchange, d.calc_wt_yest*d.iislPtsChange/d.adjustedClosePrice/100 ret
from tbl2 d 
)
,tbl8 as
(
select indexname,datetime,1+sum(ret) tot_ret from tbl7 group by indexname,datetime 
)

select indexname,datetime date
,round(exp(sum(log(sum(tot_ret))) over (partition by IndexName order by datetime)),6)*@beginval final_Ret
from tbl8 where datetime>=@startdt
 group by indexname,datetime order by date