使用递归 CTE 计算预测平均值
问题描述:
我试图回答一个问题这里,我需要计算基于前 3 个月的销售额,可以是实际值,也可以是预测值.
I was trying to answer a question here, where I need to calculate a forecast of sales based on the 3 previous months which either can be actuals or forecast.
Month Actuals Forecast
1 10
2 15
3 17
4 14.00
5 15.33
6 15.44
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
我一直在尝试使用递归 CTE:
I've been trying to do this using a recursive CTE:
;WITH cte([month],forecast) AS (
SELECT 1,CAST(10 AS DECIMAL(28,2))
UNION ALL
SELECT 2,CAST(15 AS DECIMAL(28,2))
UNION ALL
SELECT 3,CAST(17 AS DECIMAL(28,2))
UNION ALL
SELECT
[month]=[month]+1,
forecast=CAST(AVG(forecast) OVER (ORDER BY [month] ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING) AS DECIMAL(28,2))
FROM
cte
WHERE
[month]<=12
)
SELECT * FROM cte WHERE month<=12;
小提琴:http://sqlfiddle.com/#!6/9ac4a/3
但它没有按预期工作,因为它返回以下结果:
But it doesn't work as expected, as It returns the following result:
| month | forecast |
|-------|----------|
| 1 | 10 |
| 2 | 15 |
| 3 | 17 |
| 4 | (null) |
| 5 | (null) |
| 6 | (null) |
| 7 | (null) |
| 8 | (null) |
| 9 | (null) |
| 10 | (null) |
| 11 | (null) |
| 12 | (null) |
| 3 | (null) |
| 4 | (null) |
| 5 | (null) |
| 6 | (null) |
| 7 | (null) |
| 8 | (null) |
| 9 | (null) |
| 10 | (null) |
| 11 | (null) |
| 12 | (null) |
| 2 | (null) |
| 3 | (null) |
| 4 | (null) |
| 5 | (null) |
| 6 | (null) |
| 7 | (null) |
| 8 | (null) |
| 9 | (null) |
| 10 | (null) |
| 11 | (null) |
| 12 | (null) |
预期输出:
| month | forecast |
|-------|----------|
| 1 | 10 |
| 2 | 15 |
| 3 | 17 |
| 4 | 14.00 |
| 5 | 15.33 |
| 6 | 15.44 |
| 7 | 14.93 |
| 8 | 15.23 |
| 9 | 15.20 |
| 10 | 15.12 |
| 11 | 15.18 |
| 12 | 15.17 |
谁能告诉我这个查询有什么问题?
Can someone tell me what's wrong with this query?
答
我的提议是这样的:
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
输出:
+-------+----------+---------------------------+-------------------------+------------------------+
| month | forecast | three_months_ago_forecast | two_months_ago_forecast | one_month_ago_forecast |
+-------+----------+---------------------------+-------------------------+------------------------+
| 1 | 10.00 | -5.00 | 9.00 | 26.00 |
| 2 | 15.00 | 9.00 | 26.00 | 10.00 |
| 3 | 17.00 | 26.00 | 10.00 | 15.00 |
| 4 | 14.00 | 10.00 | 15.00 | 17.00 |
| 5 | 15.33 | 15.00 | 17.00 | 14.00 |
| 6 | 15.44 | 17.00 | 14.00 | 15.33 |
| 7 | 14.92 | 14.00 | 15.33 | 15.44 |
| 8 | 15.23 | 15.33 | 15.44 | 14.92 |
| 9 | 15.20 | 15.44 | 14.92 | 15.23 |
| 10 | 15.12 | 14.92 | 15.23 | 15.20 |
| 11 | 15.19 | 15.23 | 15.20 | 15.12 |
| 12 | 15.18 | 15.20 | 15.12 | 15.19 |
+-------+----------+---------------------------+-------------------------+------------------------+