问题
I'm trying to calculate a forecast of sales based on the 3 previous months which either can be actuals or forecast.
company_id Year Month Actuals Forecast
123456 2014 1 10
123456 2014 2 15
123456 2014 3 17
123456 2014 4 14.00
123456 2014 5 15.33
123456 2014 6 15.44
123456 2014 7 14.93
Month 4 = (10+15+17)/3
Month 5 = (15+17+14)/3
Month 6 = (17+14+15.33)/3
Month 7 = (14+15.33+15.44)/3
Let's say I want to calculate the forecast for the next 18 months for each company.
I'm looking at the data for last year. Some companies has e.g. 2 months of data and other 12 months and so on.
I have searched and found many different solutions but all of them only takes the actuals into account.
I think I have to make a recursive CTE, but I can't figure it out.
Please help :)
回答1:
So you want moving average based on previous moving average :) I think that when programming on SQL Server one always have to realize which tasks are more suited to set-based approach and which are more general row-by-row approach. Your task, if you ask me, is perfect for simple row-by-row processing. Here's an example
declare @temp table ([Month] int, Actual decimal(29, 2), Forecast decimal(29, 2))
declare @month int
insert into @temp (
[Month], Actual
)
select 1, 10 union all
select 2, 15 union all
select 3, 17
select @month = isnull(max([Month]) + 1, 1) from @temp
while @month <= 18
begin
insert into @temp (
[Month], Forecast
)
select
@month, avg(a.value) as Forecast
from (
select top 3 isnull(Actual, Forecast) as value
from @temp
order by [Month] desc
) as a
select @month = @month + 1
end
select * from @temp
回答2:
While I was trying to answer your question, I had another question which led to more answers to your questions: Calculate forecast average using recursive CTE
Fiddle: http://sqlfiddle.com/#!6/9ac4a/12/0
WITH T AS
(
SELECT 1 AS [month], CAST(10 AS DECIMAL(28,2)) AS [forecast], CAST(-5 AS DECIMAL(28,2)) AS three_months_ago_forecast, CAST(9 AS decimal(28,2)) AS two_months_ago_forecast, CAST(26 AS decimal(28,2)) as one_month_ago_forecast
UNION ALL
SELECT 2,CAST(15 AS DECIMAL(28,2)), CAST(9 AS decimal(28,2)), CAST(26 AS decimal(28,2)), CAST(10 AS DECIMAL(28,2))
UNION ALL
SELECT 3,CAST(17 AS DECIMAL(28,2)), CAST(26 AS decimal(28,2)), CAST(10 AS DECIMAL(28,2)), CAST(15 AS DECIMAL(28,2))
),
LT AS -- LastForecast
(
SELECT *
FROM T
WHERE [month] = 3
),
FF AS -- Future Forecast
(
SELECT *
FROM LT
UNION ALL
SELECT
FF.[month] + 1 AS [month],
CAST( (FF.forecast * 4 - FF.three_months_ago_forecast) / 3 AS decimal(28,2)) AS forecast,
FF.two_months_ago_forecast as three_months_ago_forecast,
FF.one_month_ago_forecast as two_months_ago_forecast,
FF.forecast as one_month_ago_forecast
FROM FF
WHERE
FF.[month] < 12
)
SELECT * FROM T
WHERE [month] < 3
UNION ALL
SELECT * FROM FF
来源:https://stackoverflow.com/questions/35136630/sql-calculate-forecast-average