在同一选择语句中根据先前计算的行(或列)计算新行(或列)
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,最好是create和 insert 语句,或者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。
【讨论】:
以上是关于在同一选择语句中根据先前计算的行(或列)计算新行(或列)的主要内容,如果未能解决你的问题,请参考以下文章