Multiple Levels Ranking
This documentation assumes you are familiar with the following concepts:
Introduction
The requirement to rank items in a report is a common business requirement. For example, you need to know the top-performing products in a certain aspect so you can double-down on them, or knowing the worst performing items so you can investigate for further problems.
In this guide, we will walk you through some examples of how to use the rank() function in Holistics to answer the following questions:
- What are the products with the highest sales in the whole platform?
- What are the products rankings within each category?
- Compare products’ ranks within the category and across all categories
Overall, ranking falls into two categories: Dynamic Ranking and Static Ranking.
- Dynamic Ranking: Affected by filters and dimensions, and is a metric in Holistics.
- Static Ranking: Not affected by filters and dimensions. A Static Ranking field is a dimension.
The first two questions can be answered by a ranking metric (dynamic ranking), while the third question need a ranking dimension (static ranking)
Example 1: Ranks all products by total sales
Setup
In this example, the e_commerce dataset will contain the following models: order_items , products .
- Initial Setup
- Final Setup
// order_items.model.aml
Model order_items.model.aml {
...
dimension order_id {...}
dimension product_id {...}
dimension quantity {...}
}
// products.model.aml
Model products {
...
dimension id {...}
dimension price {...}
dimension category_id {...}
}
// e_commerce.dataset.aml
Dataset e_commerce {
...
models: [order_items, products]
relationships: [
relationship(order_items.product_id > products.id, true)
]
}
// order_items.model.aml
Model order_items.model.aml {
...
dimension order_id {...}
dimension product_id {...}
dimension quantity {...}
}
// products.model.aml
Model products {
...
dimension id {...}
dimension price {...}
dimension category_id {...}
}
// e_commerce.dataset.aml
Dataset e_commerce {
...
models: [order_items, products]
relationships: [
relationship(order_items.product_id > products.id, true)
]
metric revenue {
label: 'Revenue'
type: 'number'
definition: @aql sum(order_items, order_items.quantity * products.price);;
}
metric ranking {
label: 'Ranking'
type: 'number'
definition: @aql rank(order: total_sales | desc());;
}
}
High-level flow
- Create a Revenue metric: In the
e_commercedataset, we create a simplerevenuemetric that calculate order value by summing overorder_items.quantitymultiplied byproducts.price. - Create a Ranking metric: Use the
rank()function to takerevenueas in put and generate ranking numbers in descending order (larger revenue value comes first) - Visualize: Include the Ranking metric with Product Name in the visualization to answer your questions
Implementation
1. Create a Revenue metric
In the definition file of the e_commerce dataset, we can easily create a Revenue metric that combines fields from two different models (order_items and products). This will be the basis for our ranking:
Dataset e_commerce {
...
metric revenue {
label: 'Revenue'
type: 'number'
definition: @aql coalesce(
order_items | sum(order_items.quantity * products.price),
0
) ;;
}
}
In cases where a dimension (like products, or users) have no order records, the corresponding revenue will be 0 instead of NULL. This way we do not need to worry about different ways that different databases handle NULL when ranking.
2. Create a Ranking metric
We continue to create the Ranking metric that use the Revenue metric as the ordering field. The syntax revenue | desc() is necessary if we want the revenue values are ranked in descending order.
Dataset e_commerce {
...
metric revenue {
label: 'Revenue'
type: 'number'
definition: @aql order_items | sum(order_items.quantity * products.price) ;;
}
metric ranking {
label: 'Ranking'
type: 'number'
definition: @aql rank(order: revenue | desc());;
}
}
3. Visualize
You can combine the Ranking metric with any dimensions to calculate it ranking basing on revenue. For example, here we visualize the ranking of Products:
The ranking metric can also be used to filter. For example, we can choose to display the top 3 products by revenue:
Example 2: Ranking within a category
Sometimes knowing what sells the most across the whole platform is not insightful enough - we want to know the top products within each category. In this example, we will explore how to answer this question.
Setup
The setup will be quite similar to Example 1. The only difference is that we will add the categories model to the dataset:
- Initial Setup
- Final Setup
// order_items.model.aml
Model order_items.model.aml {
...
dimension order_id {...}
dimension product_id {...}
dimension quantity {...}
}
// products.model.aml
Model products {
...
dimension id {...}
dimension price {...}
dimension category_id {...}
}
// merchants.model.aml
Model merchants {
...
dimension id {...}
dimension name {...}
}
// categories.model.aml
Model categories {
...
dimension id {...}
dimension name {...}
}
// e_commerce.dataset.aml
Dataset e_commerce {
...
models: [order_items, products, merchants]
relationships: [
relationship(order_items.product_id > products.id, true)
relationship(products.merchant_id > merchants.id, true)
relationship(products.category_id > categories.id, true)
]
}
// order_items.model.aml
Model order_items.model.aml {
...
dimension order_id {...}
dimension product_id {...}
dimension quantity {...}
}
// products.model.aml
Model products {
...
dimension id {...}
dimension price {...}
dimension category_id {...}
}
// merchants.model.aml
Model merchants {
...
dimension id {...}
dimension name {...}
}
// categories.model.aml
Model categories {
...
dimension id {...}
dimension name {...}
}
// e_commerce.dataset.aml
Dataset e_commerce {
...
models: [order_items, products, merchants]
relationships: [
relationship(order_items.product_id > products.id, true)
relationship(products.merchant_id > merchants.id, true)
relationship(products.category_id > categories.id, true)
]
metric revenue {
label: 'Revenue'
type: 'number'
definition: @aql sum(order_items, order_items.quantity * products.price);;
}
metric ranking_by_cate {
label: 'Ranking by Cate'
type: 'number'
definition: @aql rank(order: revenue | desc(), partition: categories.name);;
}
}
High-level flow
- Create a Ranking by Category metric: In this new ranking metric, we will include Category Name as the partition field
- Visualization: For this ranking metric with partition to work, we will need to include the partition field (Category Name) field in the visualization.