RunningFORECAST
Updated 2023-11-14 14:38:34.677000
Syntax
SELECT [westclintech].[wct].[RunningFORECAST](
<@New_x, float,>
,<@Y, float,>
,<@X, float,>
,<@RowNum, int,>
,<@Id, tinyint,>)
Description
Use the scalar function RunningFORECAST to calculate the predicted value of y for a specific value of x for a series of x- and y-values within a resultant table or partition, without the need for a self-join. The forecast value is calculated from the first row of the resultant table or partition through to the current row. If the column values are presented to the functions out of order, an error message will be generated.
Arguments
@Id
a unique identifier for the RunningFORECAST calculation. @Id allows you to specify multiple RunningFORECAST calculations within a resultant table. @Id is an expression of type tinyint or of a type that can be implicitly converted to tinyint.
@New_x
the specific x-value used to forecast the y-value. @New_x is an expression of type float or of a type that can be implicitly converted to float.
@RowNum
the number of the row within the group for which the sum is being calculated. If @RowNum for the current row in a set is less than or equal to the previous @RowNum and @RowNum is not equal to 1, an error message will be generated. @RowNum is an expression of type int or of a type that can be implicitly converted to int.
@X
the x-value passed into the function. @X is an expression of type float or of a type that can be implicitly converted to float.
@Y
the y-value passed into the function. @Y is an expression of type float or of a type that can be implicitly converted to float.
Return Type
float
Remarks
If @Id is NULL then @Id = 0.
@RowNum must be in ascending order.
To calculate the slope over a window of x- and y-values use the MovingFORECAST function.
If @RowNum = 1 then RunningFORECAST is NULL.
To calculate a single forecast value for a new x-value and a set of x- and y-values use the FORECAST function.
There may be cases where the order in which the data are returned to the function and the order in which the results are returned are different, generally due to parallelism. You can use OPTION(MAXDOP 1) or OPTION(MAXDOP 1,FORCE ORDER) to help eliminate this problem.
Examples
In this example we will store the monthly sales for three products: Leaf Blowers, Snow Blowers, and Pool Supplies. We will use the RunningFORECAST function to predict the new month’s sales based on the historical sales. We will use the RANK() function to number the months, with the earliest month being assigned a rank of 1.
--Create the temporary table
CREATE TABLE #f
(
EOM datetime,
item varchar(20),
sales money
);
--Populate the table with some data
INSERT INTO #f
VALUES
('2010-10-31', 'Leaf Blowers', 42548);
INSERT INTO #f
VALUES
('2010-11-30', 'Leaf Blowers', 77227);
INSERT INTO #f
VALUES
('2010-12-31', 'Leaf Blowers', 66944);
INSERT INTO #f
VALUES
('2011-01-31', 'Leaf Blowers', 34591);
INSERT INTO #f
VALUES
('2011-02-28', 'Leaf Blowers', 73468);
INSERT INTO #f
VALUES
('2011-03-31', 'Leaf Blowers', 50102);
INSERT INTO #f
VALUES
('2011-04-30', 'Leaf Blowers', 87270);
INSERT INTO #f
VALUES
('2011-05-31', 'Leaf Blowers', 51555);
INSERT INTO #f
VALUES
('2011-06-30', 'Leaf Blowers', 75139);
INSERT INTO #f
VALUES
('2011-07-31', 'Leaf Blowers', 50682);
INSERT INTO #f
VALUES
('2011-08-31', 'Leaf Blowers', 96577);
INSERT INTO #f
VALUES
('2011-09-30', 'Leaf Blowers', 77553);
INSERT INTO #f
VALUES
('2011-10-31', 'Leaf Blowers', 45299);
INSERT INTO #f
VALUES
('2011-11-30', 'Leaf Blowers', 71815);
INSERT INTO #f
VALUES
('2011-12-31', 'Leaf Blowers', 45070);
INSERT INTO #f
VALUES
('2012-01-31', 'Leaf Blowers', 60712);
INSERT INTO #f
VALUES
('2012-02-29', 'Leaf Blowers', 50021);
INSERT INTO #f
VALUES
('2012-03-31', 'Leaf Blowers', 38495);
INSERT INTO #f
VALUES
('2012-04-30', 'Leaf Blowers', 49125);
INSERT INTO #f
VALUES
('2012-05-31', 'Leaf Blowers', 49227);
INSERT INTO #f
VALUES
('2012-06-30', 'Leaf Blowers', 61511);
INSERT INTO #f
VALUES
('2012-07-31', 'Leaf Blowers', 66185);
INSERT INTO #f
VALUES
('2012-08-31', 'Leaf Blowers', 59871);
INSERT INTO #f
VALUES
('2012-09-30', 'Leaf Blowers', 69951);
INSERT INTO #f
VALUES
('2012-10-31', 'Leaf Blowers', 84861);
INSERT INTO #f
VALUES
('2012-11-30', 'Leaf Blowers', 79946);
INSERT INTO #f
VALUES
('2010-10-31', 'Snow Blowers', 77554);
INSERT INTO #f
VALUES
('2010-11-30', 'Snow Blowers', 89677);
INSERT INTO #f
VALUES
('2010-12-31', 'Snow Blowers', 75063);
INSERT INTO #f
VALUES
('2011-01-31', 'Snow Blowers', 57609);
INSERT INTO #f
VALUES
('2011-02-28', 'Snow Blowers', 65206);
INSERT INTO #f
VALUES
('2011-03-31', 'Snow Blowers', 50178);
INSERT INTO #f
VALUES
('2011-04-30', 'Snow Blowers', 41676);
INSERT INTO #f
VALUES
('2011-05-31', 'Snow Blowers', 50024);
INSERT INTO #f
VALUES
('2011-06-30', 'Snow Blowers', 35835);
INSERT INTO #f
VALUES
('2011-07-31', 'Snow Blowers', 71655);
INSERT INTO #f
VALUES
('2011-08-31', 'Snow Blowers', 69309);
INSERT INTO #f
VALUES
('2011-09-30', 'Snow Blowers', 50066);
INSERT INTO #f
VALUES
('2011-10-31', 'Snow Blowers', 77390);
INSERT INTO #f
VALUES
('2011-11-30', 'Snow Blowers', 58315);
INSERT INTO #f
VALUES
('2011-12-31', 'Snow Blowers', 83867);
INSERT INTO #f
VALUES
('2012-01-31', 'Snow Blowers', 92994);
INSERT INTO #f
VALUES
('2012-02-29', 'Snow Blowers', 67718);
INSERT INTO #f
VALUES
('2012-03-31', 'Snow Blowers', 79875);
INSERT INTO #f
VALUES
('2012-04-30', 'Snow Blowers', 30774);
INSERT INTO #f
VALUES
('2012-05-31', 'Snow Blowers', 33199);
INSERT INTO #f
VALUES
('2012-06-30', 'Snow Blowers', 33284);
INSERT INTO #f
VALUES
('2012-07-31', 'Snow Blowers', 30369);
INSERT INTO #f
VALUES
('2012-08-31', 'Snow Blowers', 50885);
INSERT INTO #f
VALUES
('2012-09-30', 'Snow Blowers', 81832);
INSERT INTO #f
VALUES
('2012-10-31', 'Snow Blowers', 72875);
INSERT INTO #f
VALUES
('2012-11-30', 'Snow Blowers', 56955);
INSERT INTO #f
VALUES
('2010-10-31', 'Pool Supplies', 67437);
INSERT INTO #f
VALUES
('2010-11-30', 'Pool Supplies', 67760);
INSERT INTO #f
VALUES
('2010-12-31', 'Pool Supplies', 36603);
INSERT INTO #f
VALUES
('2011-01-31', 'Pool Supplies', 67072);
INSERT INTO #f
VALUES
('2011-02-28', 'Pool Supplies', 71843);
INSERT INTO #f
VALUES
('2011-03-31', 'Pool Supplies', 67283);
INSERT INTO #f
VALUES
('2011-04-30', 'Pool Supplies', 62408);
INSERT INTO #f
VALUES
('2011-05-31', 'Pool Supplies', 57671);
INSERT INTO #f
VALUES
('2011-06-30', 'Pool Supplies', 95730);
INSERT INTO #f
VALUES
('2011-07-31', 'Pool Supplies', 58017);
INSERT INTO #f
VALUES
('2011-08-31', 'Pool Supplies', 88317);
INSERT INTO #f
VALUES
('2011-09-30', 'Pool Supplies', 63141);
INSERT INTO #f
VALUES
('2011-10-31', 'Pool Supplies', 43968);
INSERT INTO #f
VALUES
('2011-11-30', 'Pool Supplies', 60566);
INSERT INTO #f
VALUES
('2011-12-31', 'Pool Supplies', 33517);
INSERT INTO #f
VALUES
('2012-01-31', 'Pool Supplies', 37272);
INSERT INTO #f
VALUES
('2012-02-29', 'Pool Supplies', 76982);
INSERT INTO #f
VALUES
('2012-03-31', 'Pool Supplies', 43459);
INSERT INTO #f
VALUES
('2012-04-30', 'Pool Supplies', 66698);
INSERT INTO #f
VALUES
('2012-05-31', 'Pool Supplies', 76722);
INSERT INTO #f
VALUES
('2012-06-30', 'Pool Supplies', 88796);
INSERT INTO #f
VALUES
('2012-07-31', 'Pool Supplies', 53017);
INSERT INTO #f
VALUES
('2012-08-31', 'Pool Supplies', 93040);
INSERT INTO #f
VALUES
('2012-09-30', 'Pool Supplies', 78513);
INSERT INTO #f
VALUES
('2012-10-31', 'Pool Supplies', 45990);
INSERT INTO #f
VALUES
('2012-11-30', 'Pool Supplies', 72321);
--Calculate the monthly FORECAST for Leaf Blowers
SELECT cast(EOM as date) as EOM,
Item,
SALES,
CAST(wct.RunningFORECAST(
RANK() OVER (ORDER BY EOM) + 1,
sales,
RANK() OVER (ORDER BY EOM),
RANK() OVER (ORDER BY EOM),
NULL
) as money) as FORECAST
FROM #f
WHERE item = 'Leaf Blowers';
--Clean up
DROP TABLE #f;
This produces the following result.
{"columns":[{"field":"EOM","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"Item"},{"field":"SALES","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"FORECAST"}],"rows":[{"EOM":"2010-10-31","Item":"Leaf Blowers","SALES":"42548.00","FORECAST":"NULL"},{"EOM":"2010-11-30","Item":"Leaf Blowers","SALES":"77227.00","FORECAST":"111906.00"},{"EOM":"2010-12-31","Item":"Leaf Blowers","SALES":"66944.00","FORECAST":"86635.6667"},{"EOM":"2011-01-31","Item":"Leaf Blowers","SALES":"34591.00","FORECAST":"46789.00"},{"EOM":"2011-02-28","Item":"Leaf Blowers","SALES":"73468.00","FORECAST":"64716.80"},{"EOM":"2011-03-31","Item":"Leaf Blowers","SALES":"50102.00","FORECAST":"56894.00"},{"EOM":"2011-04-30","Item":"Leaf Blowers","SALES":"87270.00","FORECAST":"74084.2857"},{"EOM":"2011-05-31","Item":"Leaf Blowers","SALES":"51555.00","FORECAST":"65906.7857"},{"EOM":"2011-06-30","Item":"Leaf Blowers","SALES":"75139.00","FORECAST":"71219.6944"},{"EOM":"2011-07-31","Item":"Leaf Blowers","SALES":"50682.00","FORECAST":"64829.80"},{"EOM":"2011-08-31","Item":"Leaf Blowers","SALES":"96577.00","FORECAST":"77079.1818"},{"EOM":"2011-09-30","Item":"Leaf Blowers","SALES":"77553.00","FORECAST":"79385.1212"},{"EOM":"2011-10-31","Item":"Leaf Blowers","SALES":"45299.00","FORECAST":"71063.3077"},{"EOM":"2011-11-30","Item":"Leaf Blowers","SALES":"71815.00","FORECAST":"72320.5824"},{"EOM":"2011-12-31","Item":"Leaf Blowers","SALES":"45070.00","FORECAST":"66117.7429"},{"EOM":"2012-01-31","Item":"Leaf Blowers","SALES":"60712.00","FORECAST":"65149.025"},{"EOM":"2012-02-29","Item":"Leaf Blowers","SALES":"50021.00","FORECAST":"61852.9632"},{"EOM":"2012-03-31","Item":"Leaf Blowers","SALES":"38495.00","FORECAST":"56629.1503"},{"EOM":"2012-04-30","Item":"Leaf Blowers","SALES":"49125.00","FORECAST":"54606.386"},{"EOM":"2012-05-31","Item":"Leaf Blowers","SALES":"49227.00","FORECAST":"52969.0789"},{"EOM":"2012-06-30","Item":"Leaf Blowers","SALES":"61511.00","FORECAST":"53957.8333"},{"EOM":"2012-07-31","Item":"Leaf Blowers","SALES":"66185.00","FORECAST":"55653.6104"},{"EOM":"2012-08-31","Item":"Leaf Blowers","SALES":"59871.00","FORECAST":"56004.7115"},{"EOM":"2012-09-30","Item":"Leaf Blowers","SALES":"69951.00","FORECAST":"57992.5761"},{"EOM":"2012-10-31","Item":"Leaf Blowers","SALES":"84861.00","FORECAST":"62094.47"},{"EOM":"2012-11-30","Item":"Leaf Blowers","SALES":"79946.00","FORECAST":"64891.8215"}]}
In this example we will look at the monthly sales and the sales forecast side-by-side for each of the three products.
SELECT cast(f1.EOM as date) as EOM,
f1.SALES as [LB],
f2.SALES as [SB],
f3.SALES as [PS],
ROUND(
wct.RunningFORECAST(
RANK() OVER (ORDER BY f1.EOM ASC) + 1,
f1.SALES,
ROW_NUMBER() OVER (ORDER BY f1.EOM),
ROW_NUMBER() OVER (ORDER BY f1.EOM),
1
),
0
) as [LB Forecast],
ROUND(
wct.RunningFORECAST(
RANK() OVER (ORDER BY f2.EOM ASC) + 1,
f2.SALES,
ROW_NUMBER() OVER (ORDER BY f2.EOM),
ROW_NUMBER() OVER (ORDER BY f2.EOM),
2
),
0
) as [SB Forecast],
ROUND(
wct.RunningFORECAST(
RANK() OVER (ORDER BY f3.EOM ASC) + 1,
f3.SALES,
ROW_NUMBER() OVER (ORDER BY f3.EOM),
ROW_NUMBER() OVER (ORDER BY f2.EOM),
3
),
0
) as [PS Forecast]
FROM #f f1
JOIN #f f2
ON f2.EOM = f1.EOM
AND f2.item = 'Snow Blowers'
JOIN #f f3
ON f3.EOM = f1.EOM
AND f3.Item = 'Pool Supplies'
WHERE f1.item = 'Leaf Blowers';
This produces the following result.
{"columns":[{"field":"EOM","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"LB","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"SB","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"PS","headerClass":"ag-right-aligned-header","cellClass":"ag-right-aligned-cell"},{"field":"LB Forecast"},{"field":"SB Forecast"},{"field":"PS Forecast"}],"rows":[{"EOM":"2010-10-31","LB":"42548","SB":"77554","PS":"67437","LB Forecast":"NULL","SB Forecast":"NULL","PS Forecast":"NULL"},{"EOM":"2010-11-30","LB":"77227","SB":"89677","PS":"67760","LB Forecast":"111906","SB Forecast":"101800","PS Forecast":"68083"},{"EOM":"2010-12-31","LB":"66944","SB":"75063","PS":"36603","LB Forecast":"86636","SB Forecast":"78274","PS Forecast":"26433"},{"EOM":"2011-01-31","LB":"34591","SB":"57609","PS":"67072","LB Forecast":"46789","SB Forecast":"56364","PS Forecast":"51655"},{"EOM":"2011-02-28","LB":"73468","SB":"65206","PS":"71843","LB Forecast":"64717","SB Forecast":"55993","PS Forecast":"64580"},{"EOM":"2011-03-31","LB":"50102","SB":"50178","PS":"67283","LB Forecast":"56894","SB Forecast":"46440","PS Forecast":"67194"},{"EOM":"2011-04-30","LB":"87270","SB":"41676","PS":"62408","LB Forecast":"74084","SB Forecast":"37211","PS Forecast":"65658"},{"EOM":"2011-05-31","LB":"51555","SB":"50024","PS":"57671","LB Forecast":"65907","SB Forecast":"36600","PS Forecast":"62350"},{"EOM":"2011-06-30","LB":"75139","SB":"35835","PS":"95730","LB Forecast":"71220","SB Forecast":"30310","PS Forecast":"77206"},{"EOM":"2011-07-31","LB":"50682","SB":"71655","PS":"58017","LB Forecast":"64830","SB Forecast":"40847","PS Forecast":"71776"},{"EOM":"2011-08-31","LB":"96577","SB":"69309","PS":"88317","LB Forecast":"77079","SB Forecast":"47452","PS Forecast":"78989"},{"EOM":"2011-09-30","LB":"77553","SB":"50066","PS":"63141","LB Forecast":"79385","SB Forecast":"45871","PS Forecast":"75657"},{"EOM":"2011-10-31","LB":"45299","SB":"77390","PS":"43968","LB Forecast":"71063","SB Forecast":"53218","PS Forecast":"67248"},{"EOM":"2011-11-30","LB":"71815","SB":"58315","PS":"60566","LB Forecast":"72321","SB Forecast":"53362","PS Forecast":"65635"},{"EOM":"2011-12-31","LB":"45070","SB":"83867","PS":"33517","LB Forecast":"66118","SB Forecast":"60330","PS Forecast":"57176"},{"EOM":"2012-01-31","LB":"60712","SB":"92994","PS":"37272","LB Forecast":"65149","SB Forecast":"68092","PS Forecast":"51502"},{"EOM":"2012-02-29","LB":"50021","SB":"67718","PS":"76982","LB Forecast":"61853","SB Forecast":"68321","PS Forecast":"56361"},{"EOM":"2012-03-31","LB":"38495","SB":"79875","PS":"43459","LB Forecast":"56629","SB Forecast":"71198","PS Forecast":"52857"},{"EOM":"2012-04-30","LB":"49125","SB":"30774","PS":"66698","LB Forecast":"54606","SB Forecast":"63199","PS Forecast":"54908"},{"EOM":"2012-05-31","LB":"49227","SB":"33199","PS":"76722","LB Forecast":"52969","SB Forecast":"57073","PS Forecast":"58626"},{"EOM":"2012-06-30","LB":"61511","SB":"33284","PS":"88796","LB Forecast":"53958","SB Forecast":"51987","PS Forecast":"64039"},{"EOM":"2012-07-31","LB":"66185","SB":"30369","PS":"53017","LB Forecast":"55654","SB Forecast":"47193","PS Forecast":"62094"},{"EOM":"2012-08-31","LB":"59871","SB":"50885","PS":"93040","LB Forecast":"56005","SB Forecast":"46715","PS Forecast":"67404"},{"EOM":"2012-09-30","LB":"69951","SB":"81832","PS":"78513","LB Forecast":"57993","SB Forecast":"51487","PS Forecast":"69520"},{"EOM":"2012-10-31","LB":"84861","SB":"72875","PS":"45990","LB Forecast":"62094","SB Forecast":"54181","PS Forecast":"66131"},{"EOM":"2012-11-30","LB":"79946","SB":"56955","PS":"72321","LB Forecast":"64892","SB Forecast":"54076","PS Forecast":"67241"}]}