Sun*_*tel 10 cte t-sql window-functions recursive sql-server-2016
我正在尝试提出一个递归 CTE 和/或窗口函数来创建一个函数。
几天后,我将函数归结为(伪代码),我拥有N
和B
,并且需要生成E
:
E n = B n * (1 - SUM( E 1 , E 2 , ... E n-1 ))
?????????????????????????????????
? N ? B ? E ?
?????????????????????????????????
? 0 ? 0.142857143 ? 0.142857143 ?
? 1 ? 0.285714286 ? 0.244897959 ?
? 2 ? 0.285714286 ? 0.174927114 ?
? 3 ? 0.285714286 ? 0.124947938 ?
? 4 ? 0.285714286 ? 0.089248527 ?
? 5 ? 0.4 ? 0.089248527 ?
? 6 ? 0.666666667 ? 0.089248527 ?
? 7 ? 1 ? 0.044624264 ?
?????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
E 0 = 0.143 * (1 - 0) = 0.143
E 1 = 0.286 * (1 - 0.143) = 0.245
E 2 = 0.286 * (1 - (0.143 + 0.245)) = 0.175
E 3 = 0.280 * (1 - 0.143) + 0.245 + 0.175)) = 0.125
E 4 = 0.286 * (1 - (0.143 + 0.245 + 0.175 + 0.125)) = 0.089
E 5 = 0.400 * (1 - (0.143) + 0.09.0.145) + 0.09
E 6 = 0.667 * (1 - (0.143 + 0.245 + 0.175 + 0.125 + 0.089 + 0.089)) = 0.089
E 7 = 1.000 * (1 - (0.143 + 0.245) + 0.045) + 0.040 + 0.089) = 0.089
如果上表在 Excel 中,C2 = B2 * (1 - 0)
(基础)和C3 = B3 * (1 - SUM(C$2:C2))
(递归)
尝试过SUM(...) OVER(ORDER BY [N] ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
,但无法递归引用该列。
尝试了几次迭代:
?????????????????????????????????
? N ? B ? E ?
?????????????????????????????????
? 0 ? 0.142857143 ? 0.142857143 ?
? 1 ? 0.285714286 ? 0.244897959 ?
? 2 ? 0.285714286 ? 0.174927114 ?
? 3 ? 0.285714286 ? 0.124947938 ?
? 4 ? 0.285714286 ? 0.089248527 ?
? 5 ? 0.4 ? 0.089248527 ?
? 6 ? 0.666666667 ? 0.089248527 ?
? 7 ? 1 ? 0.044624264 ?
?????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
有些在 CTE 中有一个额外的列,但它只覆盖前 1 行,而第二行之后的结果是错误的。
从我尝试过的所有内容来看,似乎 CTE 的递归段是独立于其他结果计算的,并且SUM(...) OVER(...)
仅适用于当前行。(关于上表, 的所有值E
都是0.142857143
)。
我认为这是因为这UNION ALL
一切都是一次性发生的,而不是逐渐发生的。
我真正希望发生的是简化上述等式,和/或将其转换为迭代函数。
奖励:如果有人想知道此信息的来源,它可用于计算MACRS 折旧以用于税收目的。
Mar*_*ith 13
您需要一个额外的列来进行运行总计(fiddle)。
在下面 CTE 的递归部分中,R
指的是“上一”行和A
当前行,因此引用的列R
是您的SUM(E1, E2, ... En-1)
.
WITH R
AS (SELECT N,
B,
E = B,
RunningTotalE = B
FROM A
WHERE N = 0
UNION ALL
SELECT A.N,
A.B,
E = A.B * ( 1 - R.RunningTotalE ),
RunningTotalE = A.B * ( 1 - R.RunningTotalE ) + R.RunningTotalE
FROM R
JOIN A
ON A.N = R.N + 1)
SELECT N,
B,
E = CAST(E AS DECIMAL(10,9))
FROM R
Run Code Online (Sandbox Code Playgroud)