Skip to main content

Metric Expressions

Metric expressions are expressions that represent a reusable metric.

Structure

source_table_expression (optional)
| aggregation_expression
| metric_function1 (optional)
| metric_function2 (optional)
| ...

A metric expression needs to contain at least one aggregation expression, together with an optional source table expression, and an optional metric context.

Aggregation expression

An aggregation expression represents the core logic of the metric expression.

It can be a single aggregation function:

avg(users.age)

or an arithmetic combination of aggregation expressions:

// difference between average order value and average discount
avg(orders.total_value) - avg(orders.discount)

// average price of products
sum(products.price) / count(products.id)

// country order percentagage
count(orders.id) * 1.0 /
(count(orders.id) | of_all(countries))

Source table expression

A source table expression is only required if the aggregation function aggregates data from multiple models and you want to explicitly set the model to aggregate from.

For examples:

// counts number of users from users table
count(users.id)

// same as above and thus the source table expression can be omitted
users | count(users.id)

// count number of times some user placed an order
// The 'orders' part is the table expression
orders | count(users.id)

Another use case is nested aggregation where you want to aggregate on an already agregated measure. For example:

Given an existing measure:

Model users {
// Average order value of a user
measure aov {
definition: @aql
sum(order_items, order_items.quantity * products.price) * 1.0
/ count_distinct(orders.id)
;;
}
}

You can create a new nested aggregation like this

// Max of average order value of a user
// The part before 'max()' is the table expression
users | group(users.id) | select(user_aov: users.aov) | max()

Metric context

Every metric expression has a corresponding context, which includes the followings:

  • The condition applied to the expression, can be modified with where function
  • The relationship structure defined in the dataset where the expression is located, can be modified with with_relationships function
  • The level of detail associated with the expression, can be modified with LOD functions
  • The window function logic applied to the expression, can be modified with window functions

The context can be manipulated using a combination of metric functions. See the examples below for more clarity.

Examples

Count number of users:

count(users.id)

Count number of male users with where:

count(users.id) | where(users.gender == 'Male')

Cross-model metric:

sum(products.price * order_items.quantity)

Total order values, regardless of dimensions, leveraging LOD functions:

sum(products.price * order_items.quantity) | exclude(order_items)

Running Total Orders by Month

count(orders.id) | running_total(run: orders.created_at | month())

Let us know what you think about this document :)