在同一选择语句中根据先前计算的行(或列)计算新行(或列)

Posted

技术标签:

【中文标题】在同一选择语句中根据先前计算的行(或列)计算新行(或列)【英文标题】:Calculate new rows (or columns) based previously calculated rows (or columns) in same select statement 【发布时间】:2022-01-24 01:10:11 【问题描述】:

我正在尝试根据年度销售增长预期来计算年度预期销量。 在一张表中,我有实际销量:

create table #Sales (
    ProductId int,
    Year int,
    GrowthRate float
    )

insert into #Sales
values 
    (1, 2021, 1000),
    (2, 2021, 5000) 

在另一个表格中,我有年增长率:

create table #GrowthRates (
    ProductId int,
    Year int,
    GrowthRate float
    )

insert into #GrowthRates
values
    (1, 2022, 0.02),
    (1, 2023, 0.04),
    (1, 2024, 0.03),
    (1, 2025, 0.05),
    (2, 2022, 0.10),
    (2, 2023, 0.12),
    (2, 2024, 0.05),
    (2, 2025, 0.09)

有没有办法计算Sales2022 = Sales2021 * (1+GrowthRate2022),然后计算另一行Sales 2023 = Sales2022(from previously) * (1+GrowthRate2023),依此类推,直到2025年全部在select语句中完成。也许是一个循环或什么?我试图避免必须为每年创建一个中间临时表。

最终输出应该是这样的table。如果有帮助,我可以将年份转为列。

【问题讨论】:

请避免发布images 的数据,我们无法处理图片,示例数据在您的问题中应该是consumable text,最好是createinsert 语句,或者DB<>Fiddle @Stu 感谢您的指导。现在已经更正了。 您可能会使用对数和 Growthrates 表(按产品分区,按年 ASC 排序)上的窗口函数来创建运行乘积的技巧来获得累积增长率,加入回到原来的桌子。把这一切做好会有点棘手。 请向我们展示您目前的尝试。 dbfiddle.uk/… 【参考方案1】:

您可以使用recursive cte 根据上一行进行计算:

WITH recursive_cte AS
(
    -- Anchor member
    SELECT s.productid, s.year, s.growthrate from #sales s
    UNION ALL
    -- Recursive member that references expression_name.
    SELECT 
        g.productid, 
        g.year,
        r.growthrate * (1 + g.growthrate) as growthrate
    FROM #growthrates g
        INNER JOIN recursive_cte r 
            ON r.productid = g.productid AND r.year = g.year - 1
)
-- references expression name
  SELECT *
    FROM recursive_cte
ORDER BY productid, year

输出:

productid year growthrate
1 2021 1000
1 2022 1020
1 2023 1060.8
1 2024 1092.624
1 2025 1147.2552
2 2021 5000
2 2022 5500
2 2023 6160
2 2024 6468
2 2025 7050.12

如果您不想要分数,请添加舍入函数。

请参阅db<>fiddle 了解上述操作以及使用round() 的示例。

【讨论】:

感谢超级好的解决方案!非常适合我的目的。【参考方案2】:

我在这里也添加了@lptr 的仅评论答案作为正确答案,因为它是一个不错的选择并且会导致相同的结果。

此解决方案通过使用对数和窗口函数来创建一个运行乘积:

  select g.productid, 
         g.year,
         floor(s.growthrate*exp(sum(log(1+g.growthrate)) over(partition by g.productid order by g.year)))
    from #Sales as s
    join #GrowthRates as g on s.productid = g.productid 
                          and s.year < g.year
order by productid,year

@lptr 的原始解决方案请参见this db<>fiddle。

【讨论】:

以上是关于在同一选择语句中根据先前计算的行(或列)计算新行(或列)的主要内容,如果未能解决你的问题,请参考以下文章

我如何模仿新行的拖动功能,例如在 Excel 中,但在 R 中?

如何根据计算值字段选择行[重复]

在同一选择语句中计算具有不同条件的相同 id 列

根据先前计算的值计算比率

如何选择具有最新日期的行并根据该行计算另一个字段

根据行和列对矩阵中的所有元素进行排名