Aggregated Measures
How aggregation chains are built, why they must be contiguous, and what happens when the period underneath is incomplete.
An aggregated measure takes one measure and summarises it over a longer interval. It is the most numerous kind of measure in any real model, and the cheapest — it reads values Infohub already holds rather than querying an external system.
What it needs#
| Setting | Notes |
|---|---|
| Source measure | The single measure being summarised |
| Interval | The interval this measure produces, longer than the source's |
| Aggregation type | How to summarise — see Choosing the Right Aggregation Type |
| Unit | Usually the source's unit; a Counter changes the meaning but often not the unit |
| Format | Frequently fewer decimals than the source |
One aggregated measure has exactly one source. Combining several inputs is a calculated measure, not an aggregation.
Build chains one step at a time#
Aggregate Tag to Hourly, Hourly to Daily, Daily to Monthly. Do not jump from Hourly straight to Monthly even though Infohub will allow it.
Steam Flow Tag Retrieved
+-- Steam Flow Hourly Hourly Aggregated (Average)
+-- Steam Flow Daily Daily Aggregated (Average)
+-- Steam Flow Monthly Monthly Aggregated (Average)
+-- Steam Flow Weekly Weekly Aggregated (Average)
Contiguous chains give you three things a skipping chain does not.
The intermediate periods you will be asked for later. Someone always wants weekly.
Diagnosability. When the month looks wrong you can walk down — which day, then which hour — and find the gap. A chain that skips from hourly to monthly hides where the problem is.
Consistency. The monthly figure and the sum of its days agree because one is derived from the other.
Two chains from one source will disagree. Building both Daily → Monthly and Hourly → Monthly gives you two monthly measures that will differ whenever a day is partial. Pick one route and let everything above follow it.
Partial periods and weighting#
The most subtle aggregation problem is what happens when the period below is incomplete.
Consider a daily average built from hourly averages. If the plant ran for six hours, is the daily average the average of those six hours, or of twenty-four with eighteen zeros? Infohub averages the values that exist, which is almost always what you want — but it means the daily average is the average of the hours that ran, not of the day.
The problem compounds upward. A monthly average of daily averages weights every day equally, so a day with two hours of data counts as much as a full one.
Where that weighting matters, aggregate from further down. A monthly average built from the hourly measure weights every hour equally, which is usually the intended meaning. The cost is one more measure; the benefit is a number that reconciles.
A quick test for weighting problems. Compare the monthly average built from dailies against one built from hourlies for the same month. If they differ, you have partial days, and you need to decide which definition you actually want. If they agree, the question is moot.
Sums do not have this problem — a total is a total regardless of how the period was filled.
Month-to-date, year-to-date, and rolling windows#
These are common enough to be worth naming explicitly, because there are two ways to build them and one is much better.
To-date measures — MTD, YTD, WTD — are aggregations at the longer interval that accumulate as the period progresses. A month-to-date total is a Monthly measure with a Sum aggregation from the daily measure: as each day completes, the monthly value grows.
Rolling windows — "last seven days", "trailing twelve months" — are not aggregations. They are calculated measures using a window expression:
Measure_1043[-7, 0].Values.Average()
Building a rolling seven-day average as seven separate measures plus a sum is a mistake worth avoiding: it triples the model size, and it breaks the day someone asks for fourteen days instead.
Interval alignment follows the time scheme#
An aggregated measure's periods are defined by the time scheme, not by the clock. If your production day starts at 06:00, the Daily aggregation covers 06:00 to 06:00. If your financial month ends on the last Friday, the Monthly aggregation respects that.
This is one of the main reasons to aggregate in Infohub rather than asking a historian for daily values: the historian's day starts at midnight and does not know about your shifts.
Recalculation#
When a source value changes, the aggregations above it recalculate for the affected periods, and that propagates upward. Backfilling a month of history into a base measure will correctly rebuild every hourly, daily, and monthly value above it.
This is also why a large backfill is expensive: correcting a year of minutely data recalculates every interval above it for that year. Backfill deliberately, and where possible in bounded ranges.
Counter, once and only once#
A totaliser needs Counter to convert an ever-climbing register into a per-period quantity. After that conversion the values are quantities, so everything above uses Sum.
Water Meter Tag Retrieved register, climbs forever
+-- Water Hourly Hourly Counter litres used this hour
+-- Water Daily Daily Sum litres used today
+-- Water Monthly Monthly Sum
A second Counter in that chain would take the difference between two quantities, which is meaningless. If a consumption measure shows small values that look like differences of differences, look for a duplicated Counter.
Diagnosing an aggregated measure#
| Symptom | Usual cause |
|---|---|
| No values | Source measure has no values, or the measure is not deployed |
| Values far too large | Sum applied to a rate |
| Values implausibly small and flat | Average applied to a quantity |
| Huge numbers matching the raw register | Counter missing on a totaliser |
| Occasional large negative value | Totaliser rolled over or was reset without Counter |
| Daily total ≠ sum of hours | Non-contiguous chain, or two routes to the same interval |
| Monthly average looks low | Partial days weighted equally — aggregate from hourly instead |
| Correct now, wrong historically | Aggregation type changed without recalculating the old range |
Keeping the count manageable#
A full chain for every tag produces a very large model quickly. Two disciplines help.
Only build the intervals someone uses. A quarterly measure nobody has ever opened still costs storage and calculation. Add intervals when they are asked for.
Push repetition into templates. If twelve mixers each need the same eight-measure chain, that is a template instantiated twelve times, not ninety-six measures built by hand. See Templates: Concepts.