SQL CTE自递归无限循环问题及递推计算逻辑修正求助
问题与修正
问题背景
需要实现递归计算逻辑:
- 当
rn=1时,i = x / y - 当
rn>1时,i = 上一条记录的i值 / 当前y值
原代码运行时陷入无限循环,且计算结果不符合预期,期望输出如下:
| rn | x | y | i |
|---|---|---|---|
| 1 | 20 | 2 | 10.00 |
| 2 | 30 | 3 | 3.33 |
| 3 | 40 | 4 | 0.83 |
原代码:
drop table if exists #tmp create table #tmp ( rn int, x int, y int ) insert into #tmp values (1, 20, 2), (2, 30, 3), (3, 40, 4); with cte as ( select *, x / y as i from #tmp curr where rn = 1 union all select curr.rn, curr.x, curr.y, prev.x / prev.y / curr.y as i from cte curr join #tmp prev on prev.rn = curr.rn + 1 ) select * from cte option (maxrecursion 0)
问题排查
- 无限循环原因:递归CTE的关联条件逻辑错误。原代码中用递归CTE的当前记录关联
#tmp中rn = curr.rn + 1的记录,且设置了maxrecursion 0(无递归次数限制),导致每次递归都会生成新的记录,没有终止条件,最终无限循环。 - 计算逻辑错误:递归部分的
i计算错误,应该使用上一次递归得到的i值除以当前y,而非重新计算上一条的x/y再除以当前y;同时原代码用整数除法,会丢失精度。
修正后的代码
drop table if exists #tmp create table #tmp ( rn int, x int, y int ) insert into #tmp values (1, 20, 2), (2, 30, 3), (3, 40, 4); with cte as ( -- 锚点成员:初始化rn=1的记录,转换为浮点除法保留精度 select rn, x, y, cast(x * 1.0 / y as decimal(10,2)) as i from #tmp where rn = 1 union all -- 递归成员:关联下一条rn的记录,用上一次的i除以当前y select t.rn, t.x, t.y, cast(c.i / t.y as decimal(10,2)) as i from cte c join #tmp t on t.rn = c.rn + 1 ) select * from cte
运行结果
执行后得到符合预期的输出:
| rn | x | y | i |
|---|---|---|---|
| 1 | 20 | 2 | 10.00 |
| 2 | 30 | 3 | 3.33 |
| 3 | 40 | 4 | 0.83 |
内容的提问来源于stack exchange,提问作者sickless
相关产品推荐
相关产品推荐

