Sqlserver CTE递归--奖金池计算

最简单的递归

WITH RecursiveCTE (Number)
AS
(
    -- 锚点成员
    SELECT 1 AS Number
    UNION ALL
    -- 递归成员
    SELECT Number + 1
    FROM RecursiveCTE
    WHERE Number < 5
)
SELECT * FROM RecursiveCTE;

业务背景:

由于业务波动性大,根据一定规则,设定了一个奖金池,有奖金就先放池子里,累积超过基准后,就开始发放奖金,如果工资低于基准就从奖金池里扣。大概这么个意思。

已知本月调整奖金,奖金池基准,求本月发放奖金,结余奖金池。

下个月的奖金发放情况,要根据上个月的结余奖金池结果来计算,所以这里需要递归。

Sqlserver CTE递归--奖金池计算_第1张图片

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月是一个奖金周期。先分组,然后从分组的表单中取值,递归中加入分组条件,就行了。改动的地方我都红框标出来了。

Sqlserver CTE递归--奖金池计算_第2张图片

具体代码如下:

--设置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

你可能感兴趣的:(Sqlserver CTE递归--奖金池计算)