Skip to main content

Running Aggregates Reference

This page is the formal specification for Report Forge running aggregate functions. For the configuration guide see Running Aggregates. For a step-by-step tutorial see Running Aggregates Tutorial.


Function definitions

running_sum

Returns: The cumulative sum of the source field's values from the first row to the current row, in sort order.

Formula: running_sum[n] = Σ value[1..n]

Source field type: Number, Currency, Percent, or Computed (outputting a numeric type).

Null handling: Null values are treated as zero in the accumulation. The running sum continues past null rows without interruption.

Example:

RowPeriod Costrunning_sum
1100100
2null100
3200300
4150450

running_avg

Returns: The cumulative average of the source field's values from the first row to the current row, in sort order. This is a cumulative average, not a rolling window average.

Formula: running_avg[n] = Σ value[1..n] / count_non_null[1..n]

Null handling: Null values are excluded from both the numerator and denominator. The count of non-null values is used.

Example:

RowPeriod CostNon-null countrunning_avg
11001100.0
2null1100.0
32002150.0
41503150.0

running_count

Returns: The cumulative count of non-null values in the source field from the first row to the current row, in sort order.

Formula: running_count[n] = count(non_null value[1..n])

Source field type: Any field type — counts non-null occurrences.

Null handling: Null values do not increment the count.

Example:

RowRisk Descriptionrunning_count
1"Foundation issue"1
2null1
3"Wet season"2
4"Access delay"3

running_min

Returns: The minimum value seen in the source field from the first row to the current row, in sort order.

Formula: running_min[n] = MIN(value[1..n])

Null handling: Null values are ignored. The minimum is the lowest non-null value seen so far.

Example:

RowPeriod Costrunning_min
1300300
2100100
3null100
4200100

running_max

Returns: The maximum value seen in the source field from the first row to the current row, in sort order.

Formula: running_max[n] = MAX(value[1..n])

Null handling: Null values are ignored. The maximum is the highest non-null value seen so far.

Example:

RowPeriod Costrunning_max
1100100
2300300
3null300
4200300

Sort order

Running aggregates are evaluated in the sort order defined by the Sort field and Sort direction settings.

RequirementBehaviour
Sort field must be specifiedYes — without an explicit sort field, row order is undefined and results are non-deterministic
Stable sort requiredYes — if multiple rows have the same sort field value, add a tie-breaker sort field (e.g. row ID)
Sort directionAscending or Descending — controls which row is "first" in the accumulation
Multi-level sortSupported — the running aggregate follows the primary sort, then secondary sort for ties

Reset on group behaviour

When the component has grouping enabled, the Reset on group setting controls accumulation across group boundaries.

Reset on groupBehaviour
On (default)Accumulation resets to the initial state at the start of each group. Produces a per-group running aggregate.
OffAccumulation continues across group boundaries. Produces a global running aggregate ignoring groups.

Reset values by function:

FunctionReset value
running_sumResets to 0
running_avgResets numerator to 0 and non-null count to 0
running_countResets to 0
running_minResets to null (takes the first non-null value in the new group)
running_maxResets to null (takes the first non-null value in the new group)

Filter interaction

Running aggregates are computed after filters are applied. Rows excluded by a filter are not included in the accumulation.

Implication: A running_sum with a filter Period = 2026 does not include 2025 values, even if they exist in the data source. The running total starts from the first visible (unfiltered) row.

When this is the desired behaviour: Period-specific cumulative totals (e.g. cumulative spend within the current year).

When this causes issues: If you need a running total that includes pre-filter data (e.g. a cost-to-complete that must include all prior spend regardless of year filter), use a report variable with an unfiltered expression instead.


Running aggregate vs. standard aggregate

ConceptRunning aggregateStandard aggregate
Result per rowDifferent value per rowSame value for all rows
Changes with rowYes — increases/changes with each rowNo — a single summary value
Available inTable columns, chart seriesTable footer, KPI card, chart series
Use forCumulative trends, running floors/ceilingsSingle summary statistics

Edge cases

All values are null

If all source field values in the data range are null:

FunctionResult
running_sum0 for all rows
running_avgnull for all rows
running_count0 for all rows
running_minnull for all rows
running_maxnull for all rows

Single row

A running aggregate over a single row is identical to the standard aggregate for that row.

Negative values

Running aggregates handle negative values correctly. running_sum can decrease when source values are negative.

RowPeriod Costrunning_sum
1100100
2-3070
350120

Percent fields

Percent fields are stored as decimals (0.75 = 75%). Running aggregates operate on the stored decimal value, not the display percentage.

running_avg on a Percent field returns a decimal (e.g. 0.825), formatted with the % suffix as 82.5% in the output.


Component availability

Component typerunning_sumrunning_avgrunning_countrunning_minrunning_max
Table column
Line chart series
Bar chart series (combo)
Area chart series
KPI card value
Gauge
CSV export
Excel export✓ (as values)✓ (as values)✓ (as values)✓ (as values)✓ (as values)