我知道CTE等有几个递归的例子,但是如何通过在SQL Server 2012中使用窗口函数来实现这一点:
CREATE TABLE #temp
(
ID INT PRIMARY KEY IDENTITY(1,1) NOT NULL,
Percentage INT NOT NULL
)
DECLARE @Calculated MONEY = 1000
INSERT INTO #temp ( Percentage ) VALUES ( 100 )
INSERT INTO #temp ( Percentage ) VALUES ( 90)
INSERT INTO #temp ( Percentage ) VALUES ( 60)
INSERT INTO #temp ( Percentage ) VALUES ( 50)
INSERT INTO #temp ( Percentage ) VALUES ( 100)
结果将是一个像这样的运行百分比(我们从1000美元开始)
id percentage calculated
-- -------- ---------
1 100 1000
2 50 500
3 90 450
4 80 360
5 100 360
因此,下一行的值是百分比乘以该行上方的计算值。可以在计算别名上使用LAG吗?
谢谢,
答案 0 :(得分:3)
您需要一个百分比的运行产品,而不是总是比较两个连续的行,这就是为什么LEAD和LAG在这里不起作用的原因。
您可以使用窗口总和来保持百分比的运行产品与变量保持一致,以获得所需的计算结果:
SELECT
ID,
Expected,
EXP(SUM(LOG(CONVERT(FLOAT, Percentage) / 100)) OVER (ORDER BY ID)) * @Calculated AS Actual
FROM #Temp
将此添加到示例代码中(我为您的预期输出添加了一列):
CREATE TABLE #temp
(
ID INT PRIMARY KEY IDENTITY(1,1) NOT NULL,
Percentage INT NOT NULL,
Expected MONEY NOT NULL
)
DECLARE @Calculated MONEY = 1000
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 100 , 1000)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 50, 500)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 90, 450)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 80, 360)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 100, 360)
SELECT
ID,
Expected,
EXP(SUM(LOG(CONVERT(FLOAT, Percentage) / 100)) OVER (ORDER BY ID)) * @Calculated AS Actual
FROM #Temp
这将产生您的预期输出:
ID Expected Actual
----------- --------------------- ----------------------
1 1000.00 1000
2 500.00 500
3 450.00 450
4 360.00 360
5 360.00 360
答案 1 :(得分:0)
您可以使用recursive cte
来获得所需的结果
with cte
as
(
select id, percentage, 1000 as calculated
from #temp
where id =1
union all
select t.id, t.percentage, t.percentage*cte.calculated/100 as calculated
from #temp t
join cte
on t.id = cte.id+1
)
select * from cte
答案 2 :(得分:0)
我害怕,寡妇职能在这里没有帮助(至少他们不会让事情变得简单)。实现目标的最简单方法是使用双重赋值的更新语句:
alter table #temp add VAL decimal
declare @val decimal = 1000
update t set
@val = VAL = @val * Percentage / 100
from (select top 100 percent * from #temp order by id) as t
select * from #temp