SQL Server RunningAVG Function
Updated 2023-11-14 13:44:51.573000
Description
Use the scalar function RunningAVG to calculate the average of column values in an ordered resultant table, without having to do a self-join. The average value is calculated for each value from the first value to the last value in the ordered group or partition. If the column values are presented to the functions out of order, an error message will be generated.
Syntax
SELECT [westclintech].[wct].[RunningAVG] (
<@Val, float,>
,<@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.
@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 RunningAVG calculation. @Id allows you to specify multiple RunningAVG calculation s 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 moving averages, use the MovingAVG function.
To calculate moving averages for time series, use the DEMA or DWMA function.
If @RowNum is equal to 1, RunningAVG 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 in a check register from the first check to the last check. 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 running average*/
SELECT num_check,
cast(convert(varchar, date_check, 106) as char(11)) as date_check,
cast(payee as char(20)) as payee,
amt_check,
wct.RunningAvg(amt_check, num_check, NULL) as [Running AVG]
FROM #c;
This produces the following result.
| num_check | date_check | payee | amt_check | Running AVG |
|---|---|---|---|---|
| 1200 | 31 Jan 2012 | Gas Company | 108.49 | 108.49 |
| 1201 | 31 Jan 2012 | Electric Company | 98.27 | 103.38 |
| 1202 | 31 Jan 2012 | Telephone Company | 136.60 | 114.453333333333 |
| 1203 | 31 Jan 2012 | Car Leasing Company | 361.75 | 176.2775 |
| 1204 | 31 Jan 2012 | Mortgage Bank | 1129.23 | 366.868 |
| 1205 | 29 Feb 2012 | Gas Company | 153.89 | 331.371666666667 |
| 1206 | 29 Feb 2012 | Electric Company | 121.99 | 301.46 |
| 1207 | 29 Feb 2012 | Telephone Company | 138.92 | 281.1425 |
| 1208 | 29 Feb 2012 | Car Leasing Company | 361.75 | 290.098888888889 |
| 1209 | 29 Feb 2012 | Mortgage Bank | 1129.23 | 374.012 |
| 1210 | 31 Mar 2012 | Gas Company | 70.79 | 346.446363636364 |
| 1211 | 31 Mar 2012 | Electric Company | 93.57 | 325.373333333333 |
| 1212 | 31 Mar 2012 | Telephone Company | 149.78 | 311.866153846154 |
| 1213 | 31 Mar 2012 | Car Leasing Company | 361.75 | 315.429285714286 |
| 1214 | 31 Mar 2012 | Mortgage Bank | 1129.23 | 369.682666666667 |
| 1215 | 30 Apr 2012 | Gas Company | 105.58 | 353.17625 |
| 1216 | 30 Apr 2012 | Electric Company | 149.36 | 341.187058823529 |
| 1217 | 30 Apr 2012 | Telephone Company | 145.35 | 330.307222222222 |
| 1218 | 30 Apr 2012 | Car Leasing Company | 361.75 | 331.962105263158 |
| 1219 | 30 Apr 2012 | Mortgage Bank | 1129.23 | 371.8255 |
| 1220 | 31 May 2012 | Gas Company | 96.27 | 358.70380952381 |
| 1221 | 31 May 2012 | Electric Company | 114.62 | 347.609090909091 |
| 1222 | 31 May 2012 | Telephone Company | 145.43 | 338.818695652174 |
| 1223 | 31 May 2012 | Car Leasing Company | 361.75 | 339.774166666667 |
| 1224 | 31 May 2012 | Mortgage Bank | 1129.23 | 371.3524 |
| 1225 | 30 Jun 2012 | Gas Company | 147.03 | 362.724615384615 |
| 1226 | 30 Jun 2012 | Electric Company | 130.52 | 354.124444444445 |
| 1227 | 30 Jun 2012 | Telephone Company | 147.71 | 346.7525 |
| 1228 | 30 Jun 2012 | Car Leasing Company | 361.75 | 347.269655172414 |
| 1229 | 30 Jun 2012 | Mortgage Bank | 1129.23 | 373.335 |
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 RunningAVG 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,
wct.RunningAvg(amt_check, ROW_NUMBER() OVER (PARTITION BY payee ORDER BY
payee, num_check), NULL) as [Running AVG]
FROM #c
ORDER BY payee,
num_check;
This produces the following result.
| num_check | date_check | payee | amt_check | Running AVG |
|---|---|---|---|---|
| 1203 | 31 Jan 2012 | Car Leasing Company | 361.75 | 361.75 |
| 1208 | 29 Feb 2012 | Car Leasing Company | 361.75 | 361.75 |
| 1213 | 31 Mar 2012 | Car Leasing Company | 361.75 | 361.75 |
| 1218 | 30 Apr 2012 | Car Leasing Company | 361.75 | 361.75 |
| 1223 | 31 May 2012 | Car Leasing Company | 361.75 | 361.75 |
| 1228 | 30 Jun 2012 | Car Leasing Company | 361.75 | 361.75 |
| 1201 | 31 Jan 2012 | Electric Company | 98.27 | 98.27 |
| 1206 | 29 Feb 2012 | Electric Company | 121.99 | 110.13 |
| 1211 | 31 Mar 2012 | Electric Company | 93.57 | 104.61 |
| 1216 | 30 Apr 2012 | Electric Company | 149.36 | 115.7975 |
| 1221 | 31 May 2012 | Electric Company | 114.62 | 115.562 |
| 1226 | 30 Jun 2012 | Electric Company | 130.52 | 118.055 |
| 1200 | 31 Jan 2012 | Gas Company | 108.49 | 108.49 |
| 1205 | 29 Feb 2012 | Gas Company | 153.89 | 131.19 |
| 1210 | 31 Mar 2012 | Gas Company | 70.79 | 111.056666666667 |
| 1215 | 30 Apr 2012 | Gas Company | 105.58 | 109.6875 |
| 1220 | 31 May 2012 | Gas Company | 96.27 | 107.004 |
| 1225 | 30 Jun 2012 | Gas Company | 147.03 | 113.675 |
| 1204 | 31 Jan 2012 | Mortgage Bank | 1129.23 | 1129.23 |
| 1209 | 29 Feb 2012 | Mortgage Bank | 1129.23 | 1129.23 |
| 1214 | 31 Mar 2012 | Mortgage Bank | 1129.23 | 1129.23 |
| 1219 | 30 Apr 2012 | Mortgage Bank | 1129.23 | 1129.23 |
| 1224 | 31 May 2012 | Mortgage Bank | 1129.23 | 1129.23 |
| 1229 | 30 Jun 2012 | Mortgage Bank | 1129.23 | 1129.23 |
| 1202 | 31 Jan 2012 | Telephone Company | 136.60 | 136.6 |
| 1207 | 29 Feb 2012 | Telephone Company | 138.92 | 137.76 |
| 1212 | 31 Mar 2012 | Telephone Company | 149.78 | 141.766666666667 |
| 1217 | 30 Apr 2012 | Telephone Company | 145.35 | 142.6625 |
| 1222 | 31 May 2012 | Telephone Company | 145.43 | 143.216 |
| 1227 | 30 Jun 2012 | Telephone Company | 147.71 | 143.965 |
In this example we calculate 2 running averages which we will call the month-to-date (MTD) running average and the year-to-date (YTD) running average.
SELECT num_check as [check],
cast(convert(varchar, date_check, 106) as char(11)) as date_check,
cast(payee as char(20)) as payee,
amt_check,
ROUND(wct.RunningAvg(amt_check, ROW_NUMBER() OVER (PARTITION BY MONTH(
date_check)ORDER BY num_check), 1), 2) as [MTD AVG],
ROUND(wct.RunningAvg(amt_check, num_check, NULL), 2) as [YTD AVG]
FROM #c
ORDER BY num_check;
This produces the following result.
| check | date_check | payee | amt_check | MTD AVG | YTD AVG |
|---|---|---|---|---|---|
| 1200 | 31 Jan 2012 | Gas Company | 108.49 | 108.49 | 108.49 |
| 1201 | 31 Jan 2012 | Electric Company | 98.27 | 103.38 | 103.38 |
| 1202 | 31 Jan 2012 | Telephone Company | 136.60 | 114.45 | 114.45 |
| 1203 | 31 Jan 2012 | Car Leasing Company | 361.75 | 176.28 | 176.28 |
| 1204 | 31 Jan 2012 | Mortgage Bank | 1129.23 | 366.87 | 366.87 |
| 1205 | 29 Feb 2012 | Gas Company | 153.89 | 153.89 | 331.37 |
| 1206 | 29 Feb 2012 | Electric Company | 121.99 | 137.94 | 301.46 |
| 1207 | 29 Feb 2012 | Telephone Company | 138.92 | 138.27 | 281.14 |
| 1208 | 29 Feb 2012 | Car Leasing Company | 361.75 | 194.14 | 290.1 |
| 1209 | 29 Feb 2012 | Mortgage Bank | 1129.23 | 381.16 | 74.01 |
| 1210 | 31 Mar 2012 | Gas Company | 70.79 | 70.79 | 346.45 |
| 1211 | 31 Mar 2012 | Electric Company | 93.57 | 82.18 | 325.37 |
| 1212 | 31 Mar 2012 | Telephone Company | 149.78 | 104.71 | 311.87 |
| 1213 | 31 Mar 2012 | Car Leasing Company | 361.75 | 168.97 | 315.43 |
| 1214 | 31 Mar 2012 | Mortgage Bank | 1129.23 | 361.02 | 369.68 |
| 1215 | 30 Apr 2012 | Gas Company | 105.58 | 105.58 | 353.18 |
| 1216 | 30 Apr 2012 | Electric Company | 149.36 | 127.47 | 341.19 |
| 1217 | 30 Apr 2012 | Telephone Company | 145.35 | 133.43 | 330.31 |
| 1218 | 30 Apr 2012 | Car Leasing Company | 361.75 | 190.51 | 331.96 |
| 1219 | 30 Apr 2012 | Mortgage Bank | 1129.23 | 378.25 | 371.83 |
| 1220 | 31 May 2012 | Gas Company | 96.27 | 96.27 | 358.7 |
| 1221 | 31 May 2012 | Electric Company | 114.62 | 105.44 | 347.61 |
| 1222 | 31 May 2012 | Telephone Company | 145.43 | 118.77 | 338.82 |
| 1223 | 31 May 2012 | Car Leasing Company | 361.75 | 179.52 | 339.77 |
| 1224 | 31 May 2012 | Mortgage Bank | 1129.23 | 369.46 | 371.35 |
| 1225 | 30 Jun 2012 | Gas Company | 147.03 | 147.03 | 362.72 |
| 1226 | 30 Jun 2012 | Electric Company | 130.52 | 138.78 | 354.12 |
| 1227 | 30 Jun 2012 | Telephone Company | 147.71 | 141.75 | 346.75 |
| 1228 | 30 Jun 2012 | Car Leasing Company | 361.75 | 196.75 | 347.27 |
| 1229 | 30 Jun 2012 | Mortgage Bank | 1129.23 | 383.25 | 373.34 |