Create Nested Aggregation
A grasp of these concepts will help you understand this documentation better:
Introduction
Often times, an analytics problem does not stop at the first aggregation. For example, the following questions will require you to continue to aggregate the initial aggregation to a higher grain, for example:
- How does the average monthly signups change over the years?
- What is the maximum AOV of a customer in a particular country?
In this guide, we will walk through the steps to answer these questions using the Nested Aggregation feature in Holistics. As usual, we will work with the familiar Ecommerce dataset.
Example 1: Average of Monthly Signups over Years
Setup
You may see the use of measure in code snippets throughout this article. In Holistics, metrics defined inside data models are syntactically referred to as measure. We will use the word "metric" outside of code snippets to avoid confusions. Read more about Metrics here
In this first simple example, we will only work with the users model in the ecommerce dataset:
- Initial Setup
- Final Setup
// users.model.aml
Model users {
...
dimension id {...}
dimension sign_up_at {...}
}
DataSet e_commerce {
...
models: [users]
}
// users.model.aml
Model users {
...
dimension id {...}
dimension sign_up_at {...}
// Note that metrics defined in models are called measures
measure count_users {
label: 'Count Users'
type: 'number'
definition: @aql users | count(users.id) ;;
}
measure avg_of_monthly_count {
label: 'Avg. of Monthly Signups'
type: 'number'
definition: @aql users
| group(month(users.sign_up_at))
| select(users.count_users)
| average()
;;
}
}
DataSet e_commerce {
...
models: [users]
}
High-level flow
- Create the first aggregation: In the
usersmodel, create thecount_usersmetric - Create the second aggregation: Continue to create the
avg_of_monthly_singupsmetric that specify the grouping grain to sign up month, and average thecount_usersmetric - Use the second aggregation with a higher grain: In the dataset exploration UI, pull in
avg_of_monthly_signupsand thesign_up_attransformed to the Year grain.
Implementation
1. Create the first aggregation
In the users model, create a simple count_users metric:
Model users {
...
// Note that metrics defined in models are called measures
measure count_users {
label: 'Count Users'
type: 'number'
definition: @aql users | count(users.id) ;;
}
}

2. Create the second aggregation.
The logic of the avg_of_monthly_count metric is as follows:
users | group(month(users.sign_up_at)) | select(users.count_users): This part is to specifyusersas the root model to start the calculation from. Next, we select thecount_usersmetric, and group it using the month grainaverage(): The result of the previous part will be piped into this function and averaged.
In this new metric, the count_users metric will always be a count by month, and then the monthly count will be averaged across the new dimension that we include when exploring data.
Model users {
...
dimension id {...}
dimension sign_up_at {...}
// Note that metrics defined in models are called measures
measure count_users {...}
measure avg_of_monthly_count {
label: 'Avg. of Monthly Signups'
type: 'number'
definition: @aql users
| group(month(users.sign_up_at))
| select(users.count_users)
| average()
;;
}
}
3. Use the second aggregation with a higher grain
To see the effect of your setup, we can pull in the avg_of_monthly_count metric with the sign_up_at dimension which was transformed to the Year grain:
