Logo

SQL Server MovingAVG Function

Updated 2023-11-13 20:47:43.520000

Description

Use the scalar function MovingAVG to calculate the moving average of column values in an ordered resultant table, without having to do a self-join. The moving average value is calculated for each value from the first value in the window to the last value in the window. The size of the window specified in the function. If the column values are presented to the functions out of order, an error message will be generated.

Syntax

SELECT [westclintech].[wct].[MovingAVG](
  <@Val, float,>
 ,<@Offset, int,>
 ,<@RowNum, int,>
 ,<@Id, tinyint,>)

Arguments

@Val

the value passed into the function. @Val is an expression of type float or of a type that can be implicitly converted to float.

@Offset

specifies the window size. @Offset is an expression of type int or of a type that can be implicitly converted to int.

@RowNum

the number of the row within the group for which the average 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.

@Id

a unique identifier for the MovingAVG calculation. @Id allows you to specify multiple moving averages within a resultant table. @Id is an expression of type tinyint or of a type that can be implicitly converted to tinyint.

Return Type

float

Remarks

If @Id is NULL then @Id = 0.

To calculate running averages from the beginning of the dataset or parition, use the RunningAVG function.

To calculate moving averages for time series, use the DEMA or DWMA function.

If @RowNum is equal to 1, MovingAVG is equal to @Val.

@RowNum must be in ascending order.

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 calculate the average check amount for the current and preceding 5 rows in a check register. We will create a temporary table, #c, populate it with some data and then run the SELECT.

/*Create the temporary table*/
CREATE TABLE #c
(
    num_check int,
    date_check datetime,
    payee varchar(50),
    amt_check money,
    Primary Key (num_check)
);
/*Populate the table with some data*/
INSERT INTO #c
VALUES
(1200, '2012-01-31', 'Gas Company', 108.49);
INSERT INTO #c
VALUES
(1201, '2012-01-31', 'Electric Company', 98.27);
INSERT INTO #c
VALUES
(1202, '2012-01-31', 'Telephone Company', 136.6);
INSERT INTO #c
VALUES
(1203, '2012-01-31', 'Car Leasing Company', 361.75);
INSERT INTO #c
VALUES
(1204, '2012-01-31', 'Mortgage Bank', 1129.23);
INSERT INTO #c
VALUES
(1205, '2012-02-29', 'Gas Company', 153.89);
INSERT INTO #c
VALUES
(1206, '2012-02-29', 'Electric Company', 121.99);
INSERT INTO #c
VALUES
(1207, '2012-02-29', 'Telephone Company', 138.92);
INSERT INTO #c
VALUES
(1208, '2012-02-29', 'Car Leasing Company', 361.75);
INSERT INTO #c
VALUES
(1209, '2012-02-29', 'Mortgage Bank', 1129.23);
INSERT INTO #c
VALUES
(1210, '2012-03-31', 'Gas Company', 70.79);
INSERT INTO #c
VALUES
(1211, '2012-03-31', 'Electric Company', 93.57);
INSERT INTO #c
VALUES
(1212, '2012-03-31', 'Telephone Company', 149.78);
INSERT INTO #c
VALUES
(1213, '2012-03-31', 'Car Leasing Company', 361.75);
INSERT INTO #c
VALUES
(1214, '2012-03-31', 'Mortgage Bank', 1129.23);
INSERT INTO #c
VALUES
(1215, '2012-04-30', 'Gas Company', 105.58);
INSERT INTO #c
VALUES
(1216, '2012-04-30', 'Electric Company', 149.36);
INSERT INTO #c
VALUES
(1217, '2012-04-30', 'Telephone Company', 145.35);
INSERT INTO #c
VALUES
(1218, '2012-04-30', 'Car Leasing Company', 361.75);
INSERT INTO #c
VALUES
(1219, '2012-04-30', 'Mortgage Bank', 1129.23);
INSERT INTO #c
VALUES
(1220, '2012-05-31', 'Gas Company', 96.27);
INSERT INTO #c
VALUES
(1221, '2012-05-31', 'Electric Company', 114.62);
INSERT INTO #c
VALUES
(1222, '2012-05-31', 'Telephone Company', 145.43);
INSERT INTO #c
VALUES
(1223, '2012-05-31', 'Car Leasing Company', 361.75);
INSERT INTO #c
VALUES
(1224, '2012-05-31', 'Mortgage Bank', 1129.23);
INSERT INTO #c
VALUES
(1225, '2012-06-30', 'Gas Company', 147.03);
INSERT INTO #c
VALUES
(1226, '2012-06-30', 'Electric Company', 130.52);
INSERT INTO #c
VALUES
(1227, '2012-06-30', 'Telephone Company', 147.71);
INSERT INTO #c
VALUES
(1228, '2012-06-30', 'Car Leasing Company', 361.75);
INSERT INTO #c
VALUES
(1229, '2012-06-30', 'Mortgage Bank', 1129.23);
/*Calculate the moving average*/
SELECT num_check,
       cast(date_check as date) as date_check,
       cast(payee as char(20)) as payee,
       amt_check,
       wct.MovingAVG(amt_check, 5, num_check, NULL) as [Moving AVG]
FROM #c;
--Clean up
DROP TABLE #c;

This produces the following result.

num_checkdate_checkpayeeamt_checkMoving AVG
12002012-01-31Gas Company108.49108.49
12012012-01-31Electric Company98.27103.38
12022012-01-31Telephone Company136.60114.453333333333
12032012-01-31Car Leasing Company361.75176.2775
12042012-01-31Mortgage Bank1129.23366.868
12052012-02-29Gas Company153.89331.371666666667
12062012-02-29Electric Company121.99333.621666666667
12072012-02-29Telephone Company138.92340.396666666667
12082012-02-29Car Leasing Company361.75377.921666666667
12092012-02-29Mortgage Bank1129.23505.835
12102012-03-31Gas Company70.79329.428333333333
12112012-03-31Electric Company93.57319.375
12122012-03-31Telephone Company149.78324.006666666667
12132012-03-31Car Leasing Company361.75361.145
12142012-03-31Mortgage Bank1129.23489.058333333333
12152012-04-30Gas Company105.58318.45
12162012-04-30Electric Company149.36331.545
12172012-04-30Telephone Company145.35340.175
12182012-04-30Car Leasing Company361.75375.503333333333
12192012-04-30Mortgage Bank1129.23503.416666666667
12202012-05-31Gas Company96.27331.256666666667
12212012-05-31Electric Company114.62332.763333333333
12222012-05-31Telephone Company145.43332.108333333333
12232012-05-31Car Leasing Company361.75368.175
12242012-05-31Mortgage Bank1129.23496.088333333333
12252012-06-30Gas Company147.03332.388333333333
12262012-06-30Electric Company130.52338.096666666667
12272012-06-30Telephone Company147.71343.611666666667
12282012-06-30Car Leasing Company361.75379.665
12292012-06-30Mortgage Bank1129.23507.578333333333

In this example, we calculate the average by payee in date order and use the ROW_NUMBER() function to determine the @RowNum value passed into the MovingAVG function.

SELECT num_check,
       cast(convert(varchar, date_check, 106) as char(11)) as date_check,
       cast(payee as char(20)) as payee,
       amt_check,
       ROUND(wct.MovingAvg(amt_check, 3, ROW_NUMBER() OVER (PARTITION BY payee 
                 ORDER BY payee, num_check), NULL), 2) as [Moving AVG]
FROM #c
ORDER BY payee,
         num_check;

This produces the following result.

num_checkdate_checkpayeeamt_checkMoving AVG
120331 Jan 2012Car Leasing Company361.75361.75
120829 Feb 2012Car Leasing Company361.75361.75
121331 Mar 2012Car Leasing Company361.75361.75
121830 Apr 2012Car Leasing Company361.75361.75
122331 May 2012Car Leasing Company361.75361.75
122830 Jun 2012Car Leasing Company361.75361.75
120131 Jan 2012Electric Company98.2798.27
120629 Feb 2012Electric Company121.99110.13
121131 Mar 2012Electric Company93.57104.61
121630 Apr 2012Electric Company149.36115.8
122131 May 2012Electric Company114.62119.89
122630 Jun 2012Electric Company130.52122.02
120031 Jan 2012Gas Company108.49108.49
120529 Feb 2012Gas Company153.89131.19
121031 Mar 2012Gas Company70.79111.06
121530 Apr 2012Gas Company105.58109.69
122031 May 2012Gas Company96.27106.63
122530 Jun 2012Gas Company147.03104.92
120431 Jan 2012Mortgage Bank1129.231129.23
120929 Feb 2012Mortgage Bank1129.231129.23
121431 Mar 2012Mortgage Bank1129.231129.23
121930 Apr 2012Mortgage Bank1129.231129.23
122431 May 2012Mortgage Bank1129.231129.23
122930 Jun 2012Mortgage Bank1129.231129.23
120231 Jan 2012Telephone Company136.60136.6
120729 Feb 2012Telephone Company138.92137.76
121231 Mar 2012Telephone Company149.78141.77
121730 Apr 2012Telephone Company145.35142.66
122231 May 2012Telephone Company145.43144.87
122730 Jun 2012Telephone Company147.71147.07