SQL Server窗口函数用于运行百分比

时间:2015-01-23 02:54:52

标签: sql sql-server

我知道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吗?

谢谢,

3 个答案:

答案 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