最简单的递归
WITH RecursiveCTE (Number)
AS
(
-- 锚点成员
SELECT 1 AS Number
UNION ALL
-- 递归成员
SELECT Number + 1
FROM RecursiveCTE
WHERE Number < 5
)
SELECT * FROM RecursiveCTE;
业务背景:
由于业务波动性大,根据一定规则,设定了一个奖金池,有奖金就先放池子里,累积超过基准后,就开始发放奖金,如果工资低于基准就从奖金池里扣。大概这么个意思。
已知本月调整奖金,奖金池基准,求本月发放奖金,结余奖金池。
下个月的奖金发放情况,要根据上个月的结余奖金池结果来计算,所以这里需要递归。
WITH CTE_Bonus (计件团体编码,计件团体名称,YYMM,奖金池周期开始,奖金池周期截止,COUNTS,异常补贴金额,本月调整奖金,奖金池基准,本月发放奖金,结余奖金池,上月奖金池)
AS (
-- 初始查询,选择第一个月的数据
SELECT 计件团体编码,计件团体名称,YYMM,奖金池周期开始,奖金池周期截止,COUNTS,异常补贴金额,本月调整奖金,奖金池基准
,CASE WHEN 本月调整奖金 >= 奖金池基准 THEN 本月调整奖金 - 奖金池基准 ELSE 0 END AS 本月发放奖金
,CASE WHEN 本月调整奖金 >= 奖金池基准 THEN 奖金池基准 ELSE 本月调整奖金 END AS 结余奖金池
,CAST(0 AS FLOAT) AS 上月奖金池
FROM GZ02
WHERE COUNTS = 1
UNION ALL
-- 递归部分,计算后续月份的数据
SELECT T.计件团体编码,T.计件团体名称,T.YYMM,T.奖金池周期开始,T.奖金池周期截止,T.COUNTS,T.异常补贴金额,T.本月调整奖金,T.奖金池基准
,CASE WHEN T.本月调整奖金 + C.结余奖金池 >= T.奖金池基准 THEN (T.本月调整奖金 + C.结余奖金池 )- T.奖金池基准 ELSE 0 END AS 本月发放奖金
,CASE WHEN T.本月调整奖金 + C.结余奖金池 >= T.奖金池基准 THEN T.奖金池基准 ELSE (T.本月调整奖金 + C.结余奖金池 ) END AS 结余奖金池
,C.结余奖金池 AS 上月奖金池
FROM GZ02 T
JOIN CTE_Bonus C ON T.COUNTS = C.COUNTS + 1
)
SELECT * FROM CTE_Bonus
只用1个计件团体,每月无限递归下去,这样验证的话,是对的。
然后升级难度,有多个计件团体,每年2-次年1月是一个奖金周期。先分组,然后从分组的表单中取值,递归中加入分组条件,就行了。改动的地方我都红框标出来了。
具体代码如下:
--设置CTE分组(已根据计件团体、奖金池周期设置counts)
,GroupCTE AS(
SELECT 计件团体编码,计件团体名称
,YYMM,奖金池周期开始,奖金池周期截止,COUNTS,异常补贴金额,本月调整奖金,奖金池基准
FROM
GZ02
)
,CTE_Bonus (计件团体编码,计件团体名称,YYMM,奖金池周期开始,奖金池周期截止,COUNTS,异常补贴金额,本月调整奖金,奖金池基准,本月发放奖金,结余奖金池,上月奖金池)
AS (
-- 初始查询,选择第一个月的数据
SELECT 计件团体编码,计件团体名称,YYMM,奖金池周期开始,奖金池周期截止,COUNTS,异常补贴金额,本月调整奖金,奖金池基准
,CASE WHEN 本月调整奖金 >= 奖金池基准 THEN 本月调整奖金 - 奖金池基准 ELSE 0 END AS 本月发放奖金
,CASE WHEN 本月调整奖金 >= 奖金池基准 THEN 奖金池基准 ELSE 本月调整奖金 END AS 结余奖金池
,CAST(0 AS FLOAT) AS 上月奖金池
FROM GroupCTE
WHERE COUNTS = 1
UNION ALL
-- 递归部分,计算后续月份的数据
SELECT T.计件团体编码,T.计件团体名称,T.YYMM,T.奖金池周期开始,T.奖金池周期截止,T.COUNTS,T.异常补贴金额,T.本月调整奖金,T.奖金池基准
,CASE WHEN T.本月调整奖金 + C.结余奖金池 >= T.奖金池基准 THEN (T.本月调整奖金 + C.结余奖金池 )- T.奖金池基准 ELSE 0 END AS 本月发放奖金
,CASE WHEN T.本月调整奖金 + C.结余奖金池 >= T.奖金池基准 THEN T.奖金池基准 ELSE (T.本月调整奖金 + C.结余奖金池 ) END AS 结余奖金池
,C.结余奖金池 AS 上月奖金池
FROM GroupCTE T
JOIN CTE_Bonus C ON T.COUNTS = C.COUNTS + 1 AND T.奖金池周期开始 = C.奖金池周期开始 AND T.计件团体编码 = C.计件团体编码
)
SELECT * FROM CTE_Bonus