Create a continuous aggregate on top of another continuous aggregate
Creating a on top of another works the same way as creating it on top of a . In your query, select from a rather than from the , and use the time-bucketed column from the existing as your time column. For more information, see the instructions for creating a continuous aggregate.Use real-time aggregation with hierarchical continuous aggregates
Real-time aggregates always return up-to-date data in response to queries. They accomplish this by joining the materialized data in the with unmaterialized raw data from the source table or view. When s are stacked, each is only aware of the layer immediately below. The joining of unmaterialized data happens recursively until it reaches the bottom layer, giving you access to recent data down to that layer. If you keep all s in the stack as real-time aggregates, the bottom layer is the source . That means every in the stack has access to all recent data. If there is a non-real-time somewhere in the stack, the recursive joining stops at that non-real-time . Higher-level s don’t receive any unmaterialized data from lower levels. For example, say you have the following s:- A real-time hourly on the source
- A real-time daily on the hourly
- A non-real-time, or materialized-only, monthly on the daily
- A real-time yearly on the monthly
- Make the monthly real-time, or
- Redefine the yearly on top of the daily .
Roll up calculations
When summarizing already-summarized data, be aware of how stacked calculations work. Not all calculations return the correct result if you stack them. For example, if you take the maximum of several subsets, then take the maximum of the maximums, you get the maximum of the entire set. But if you take the average of several subsets, then take the average of the averages, that can result in a different figure than the average of all the data. To simplify such calculations when using s on top of s, you can use the hyperfunctions from TimescaleDB Toolkit, such as the statistical aggregates. These hyperfunctions are designed with a two-step aggregation pattern that allows you to roll them up into larger buckets. The first step creates a summary aggregate that can be rolled up, just as a maximum can be rolled up. You can store this aggregate in your . Then, you can call an accessor function as a second step when you query from your . This accessor takes the stored data from the summary aggregate and returns the final result. For example, you can create an hourly usingpercentile_agg over a , like this:
rollup function, like this:
mean function of the TimescaleDB Toolkit is used to calculate the concrete mean value of the rolled
up values. The additional percentile_daily attribute contains the raw rolled up values, which can be
used in an additional on top of this (for example a for the daily values).
For more information and examples about using rollup functions to stack calculations, see the
percentile approximation API documentation.
Restrictions
There are some restrictions when creating a on top of another . In most cases, these restrictions are in place to ensure valid time-bucketing:- You can only create a on top of a finalized . This new finalized format is the default for all s created since 2.7. If you need to create a on top of a in the old format, you need to migrate your continuous aggregate to the new format first.
- The time bucket of a should be greater than or equal to the time bucket of the underlying . It also needs to be a multiple of the underlying time bucket. For example, you can rebucket an hourly into a new with time buckets of 6 hours. You can’t rebucket the hourly into a new with time buckets of 90 minutes, because 90 minutes is not a multiple of 1 hour.
-
A with a fixed-width time bucket can’t be created on top of a with a variable-width time
bucket. Fixed-width time buckets are time buckets defined in seconds, minutes, hours, and days, because
those time intervals are always the same length. Variable-width time buckets are time buckets defined in
months or years, because those time intervals vary by the month or on leap years. This limitation
prevents a case such as trying to rebucket monthly buckets into
61 daybuckets, where there is no good mapping between time buckets for month combinations such as July/August (62 days). Note that even though weeks are fixed-width intervals, you can’t use monthly or yearly time buckets on top of weekly time buckets for the same reason. The number of weeks in a month or year is usually not an integer. However, you can stack a variable-width time bucket on top of a fixed-width time bucket. For example, creating a monthly on top of a daily works, and is one of the main use cases for this feature.