Logo

SQL Server MovingCOUNT Function

Updated 2023-11-13 21:10:18.487000

Description

Use the scalar function MovingCOUNT to show how many rows are included in an ordered resultant table or within a partition in the resultant table, without having to do a self-join. The count is calculated for each value from the first value in the window to the last value in the window. If the column values are presented to the functions out of order, an error message will be generated.

Syntax

SELECT [westclintech].[wct].[MovingCOUNT](
  <@Val, sql_variant,>
 ,<@Offset, int,>
 ,<@RowNum, int,>
 ,<@Id, tinyint,>
 ,<@CountNulls, bit,>)

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 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.

@Id

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

@CountNulls

Indicates whether NULL values are included in the count. Enter 'True' to count NULL or 'False' not to count NULL. @CountNulls is an expression of type bit or of a type that can be implicitly converted to bit.

Return Type

float

Remarks

If @Id is NULL then @Id = 0.

To calculate a running count from the first record in a dataset or partition, use the RunningCOUNT function.

@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 running count of items for a check book. We will create a temporary table, #c, populate it with some data and then run the SELECT.

--Create the temporary table
CREATE TABLE #c
(
    trn int,
    cust_ref varchar(5),
    date_trn datetime,
    payee varchar(20),
    amt_trn money,
    PRIMARY KEY (trn)
);
--Populate the table with some data
INSERT INTO #c
VALUES
(1, 'DD', '2011-12-23', NULL, 1500);
INSERT INTO #c
VALUES
(2, '1200', '2012-01-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(3, '1201', '2012-01-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(4, 'DD', '2012-01-08', NULL, 1100);
INSERT INTO #c
VALUES
(5, '1202', '2012-01-15', 'Gas Company', -108.49);
INSERT INTO #c
VALUES
(6, '1203', '2012-01-15', 'Electric Company', -98.27);
INSERT INTO #c
VALUES
(7, '1204', '2012-01-15', 'Telephone Company', -136.6);
INSERT INTO #c
VALUES
(8, 'DD', '2012-02-15', NULL, 1100);
INSERT INTO #c
VALUES
(9, '1205', '2012-02-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(10, '1206', '2012-02-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(11, 'DD', '2012-02-08', NULL, 1100);
INSERT INTO #c
VALUES
(12, '1207', '2012-02-15', 'Gas Company', -153.89);
INSERT INTO #c
VALUES
(13, '1208', '2012-02-15', 'Electric Company', -121.99);
INSERT INTO #c
VALUES
(14, '1209', '2012-02-15', 'Telephone Company', -138.92);
INSERT INTO #c
VALUES
(15, 'DD', '2012-02-23', NULL, 1100);
INSERT INTO #c
VALUES
(16, '1210', '2012-03-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(17, '1211', '2012-03-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(18, 'DD', '2012-03-08', NULL, 1100);
INSERT INTO #c
VALUES
(19, '1212', '2012-03-15', 'Gas Company', -70.79);;
INSERT INTO #c
VALUES
(20, '1213', '2012-03-15', 'Electric Company', -93.57);
INSERT INTO #c
VALUES
(21, '1214', '2012-03-15', 'Telephone Company', -149.78);
INSERT INTO #c
VALUES
(22, 'DD', '2012-03-23', NULL, 1100);
INSERT INTO #c
VALUES
(23, '1215', '2012-04-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(24, '1216', '2012-04-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(25, 'DD', '2012-04-08', NULL, 1100);
INSERT INTO #c
VALUES
(26, '1217', '2012-04-15', 'Gas Company', -105.58);
INSERT INTO #c
VALUES
(27, '1218', '2012-04-15', 'Electric Company', -149.36);
INSERT INTO #c
VALUES
(28, '1219', '2012-04-15', 'Telephone Company', -145.35);
INSERT INTO #c
VALUES
(29, 'DD', '2012-04-23', NULL, 1100);
INSERT INTO #c
VALUES
(30, '1220', '2012-05-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(31, '1221', '2012-05-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(32, 'DD', '2012-05-08', NULL, 1100);
INSERT INTO #c
VALUES
(33, '1222', '2012-05-15', 'Gas Company', -96.27);
INSERT INTO #c
VALUES
(34, '1223', '2012-05-15', 'Electric Company', -114.62);
INSERT INTO #c
VALUES
(35, '1224', '2012-05-15', 'Telephone Company', -145.43);
INSERT INTO #c
VALUES
(36, 'DD', '2012-05-23', NULL, 1100);
INSERT INTO #c
VALUES
(37, '1225', '2012-06-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(38, '1226', '2012-06-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(39, 'DD', '2012-06-08', NULL, 1100);
INSERT INTO #c
VALUES
(40, '1227', '2012-06-15', 'Gas Company', -147.03);
INSERT INTO #c
VALUES
(41, '1228', '2012-06-15', 'Electric Company', -130.52);
INSERT INTO #c
VALUES
(42, '1229', '2012-06-15', 'Telephone Company', -147.71);
INSERT INTO #c
VALUES
(43, 'DD', '2012-06-23', NULL, 1100);
INSERT INTO #c
VALUES
(44, '1230', '2012-07-01', 'Car Leasing Company', -361.75);
INSERT INTO #c
VALUES
(45, '1231', '2012-07-01', 'Mortgage Bank', -1129.23);
INSERT INTO #c
VALUES
(46, 'DD', '2012-07-08', NULL, 1100);
--Calculate the moving COUNT
SELECT cast(convert(varchar, date_trn, 106) as char(11)) as date_trn,
       cust_ref,
       payee,
       amt_trn,
       wct.MovingCOUNT(payee, 5, trn, NULL, 'False') as [Moving Count]
FROM #c;
--Clean up
DROP TABLE #c;

This produces the following result.

date_trncust_refpayeeamt_trnMoving Count
23 Dec 2011DDNULL1500.000
01 Jan 20121200Car Leasing Company-361.751
01 Jan 20121201Mortgage Bank-1129.232
08 Jan 2012DDNULL1100.002
15 Jan 20121202Gas Company-108.493
15 Jan 20121203Electric Company-98.274
15 Jan 20121204Telephone Company-136.605
15 Feb 2012DDNULL1100.004
01 Feb 20121205Car Leasing Company-361.754
01 Feb 20121206Mortgage Bank-1129.235
08 Feb 2012DDNULL1100.004
15 Feb 20121207Gas Company-153.894
15 Feb 20121208Electric Company-121.994
15 Feb 20121209Telephone Company-138.925
23 Feb 2012DDNULL1100.004
01 Mar 20121210Car Leasing Company-361.754
01 Mar 20121211Mortgage Bank-1129.235
08 Mar 2012DDNULL1100.004
15 Mar 20121212Gas Company-70.794
15 Mar 20121213Electric Company-93.574
15 Mar 20121214Telephone Company-149.785
23 Mar 2012DDNULL1100.004
01 Apr 20121215Car Leasing Company-361.754
01 Apr 20121216Mortgage Bank-1129.235
08 Apr 2012DDNULL1100.004
15 Apr 20121217Gas Company-105.584
15 Apr 20121218Electric Company-149.364
15 Apr 20121219Telephone Company-145.355
23 Apr 2012DDNULL1100.004
01 May 20121220Car Leasing Company-361.754
01 May 20121221Mortgage Bank-1129.235
08 May 2012DDNULL1100.004
15 May 20121222Gas Company-96.274
15 May 20121223Electric Company-114.624
15 May 20121224Telephone Company-145.435
23 May 2012DDNULL1100.004
01 Jun 20121225Car Leasing Company-361.754
01 Jun 20121226Mortgage Bank-1129.235
08 Jun 2012DDNULL1100.004
15 Jun 20121227Gas Company-147.034
15 Jun 20121228Electric Company-130.524
15 Jun 20121229Telephone Company-147.715
23 Jun 2012DDNULL1100.004
01 Jul 20121230Car Leasing Company-361.754
01 Jul 20121231Mortgage Bank-1129.235
08 Jul 2012DDNULL1100.004

In this example, we calculate the running count and the running count for each month and use the ROW_NUMBER() function to determine the @RowNum value passed into the MovingCOUNT function.

SELECT CAST(date_trn as date) as date_trn,
       cust_ref,
       payee,
       amt_trn,
       wct.MovingCOUNT(payee, 5, ROW_NUMBER() OVER (PARTITION by MONTH(date_trn)
                 ORDER BY trn), 1, 'False') as [MTD Count],
       wct.MovingCOUNT(amt_trn, 5, trn, NULL, 'False') as [Moving Ct]
FROM #c
ORDER BY trn;

This produces the following result.

date_trncust_refpayeeamt_trnMTD CountMoving Ct
2011-12-23DDNULL1500.0001
2012-01-011200Car Leasing Company-361.7512
2012-01-011201Mortgage Bank-1129.2323
2012-01-08DDNULL1100.0024
2012-01-151202Gas Company-108.4935
2012-01-151203Electric Company-98.2746
2012-01-151204Telephone Company-136.6056
2012-02-15DDNULL1100.0006
2012-02-011205Car Leasing Company-361.7516
2012-02-011206Mortgage Bank-1129.2326
2012-02-08DDNULL1100.0026
2012-02-151207Gas Company-153.8936
2012-02-151208Electric Company-121.9946
2012-02-151209Telephone Company-138.9256
2012-02-23DDNULL1100.0046
2012-03-011210Car Leasing Company-361.7516
2012-03-011211Mortgage Bank-1129.2326
2012-03-08DDNULL1100.0026
2012-03-151212Gas Company-70.7936
2012-03-151213Electric Company-93.5746
2012-03-151214Telephone Company-149.7856
2012-03-23DDNULL1100.0046
2012-04-011215Car Leasing Company-361.7516
2012-04-011216Mortgage Bank-1129.2326
2012-04-08DDNULL1100.0026
2012-04-151217Gas Company-105.5836
2012-04-151218Electric Company-149.3646
2012-04-151219Telephone Company-145.3556
2012-04-23DDNULL1100.0046
2012-05-011220Car Leasing Company-361.7516
2012-05-011221Mortgage Bank-1129.2326
2012-05-08DDNULL1100.0026
2012-05-151222Gas Company-96.2736
2012-05-151223Electric Company-114.6246
2012-05-151224Telephone Company-145.4356
2012-05-23DDNULL1100.0046
2012-06-011225Car Leasing Company-361.7516
2012-06-011226Mortgage Bank-1129.2326
2012-06-08DDNULL1100.0026
2012-06-151227Gas Company-147.0336
2012-06-151228Electric Company-130.5246
2012-06-151229Telephone Company-147.7156
2012-06-23DDNULL1100.0046
2012-07-011230Car Leasing Company-361.7516
2012-07-011231Mortgage Bank-1129.2326
2012-07-08DDNULL1100.0026