在 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
我有以下 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