# Metrics by Example
> Find the AQL pattern that fits your question: by intent, by metric shape, or by copy-paste snippet. Built on a shared e-commerce schema.
The Cookbook landing page. Three ways to find what you need:
- **[By question](#by-question)**: "I want to do X" → the page that shows you how.
- **[By metric shape](#by-metric-shape)**: what shape is the metric, and which function handles it.
- **[Snippet gallery](#snippet-gallery)**: copy-paste AML for the most common patterns.
## Shared e-commerce schema
Most examples on this page and across the Cookbook use this schema:
**Models:** `users`, `orders`, `order_items`, `products`, `categories`, `merchants`, `cities`, `countries`.
**Key relationships:**
- `order_items` → `orders` (many:1) via `order_id`
- `order_items` → `products` (many:1) via `product_id`
- `orders` → `users` (many:1) via `user_id`
- `users` → `cities` → `countries` (geographic chain)
- `products` → `categories` (many:1)
- `products` → `merchants` (many:1)
## By question
When you know the *question* but not the *AQL feature*:
| I want to… | Go to |
|---|---|
| Slice a metric by a dimension and add filters | [Learn → Filtering](/as-code/aql/learn/filtering), [Grouping](/as-code/aql/learn/grouping) |
| Define a reusable metric or AQL dimension | [Learn → Defining a Metric](/as-code/aql/learn/defining-a-metric) |
| Build a metric that spans multiple models | [Learn → Cross-Model Queries](/as-code/aql/learn/cross-model) |
| Compute a ratio (e.g. completion rate) | [Learn → Defining a Metric](/as-code/aql/learn/defining-a-metric#metrics-compose), [Cookbook → Percent of Total](/as-code/aql/cookbook/aql-percent-of-total) |
| Segment customers with a boolean flag (VIP, churned, etc.) | [Cookbook → LoD Patterns](/as-code/aql/cookbook/level-of-detail#use-case-3-customer-segmentation-flag--dimensionalize-for-filtering) |
| Bucket records into tiers (deciles, quartiles) | [Cookbook → Ranking](/as-code/aql/cookbook/aql-rank#example-4-performance-tiers-with-ntile) |
| Compute percent of total | [Learn → Level of Detail](/as-code/aql/learn/level-of-detail), [Cookbook → Percent of Total](/as-code/aql/cookbook/aql-percent-of-total) |
| Aggregate already-aggregated data (avg of monthly totals, max of per-user metric) | [Learn → Nested Aggregation](/as-code/aql/learn/nested-aggregation), [Cookbook → Nested Aggregation](/as-code/aql/cookbook/aql-nested-aggregation) |
| Rank items, with or without partitions | [Cookbook → Ranking](/as-code/aql/cookbook/aql-rank) |
| Year-over-year, quarter-over-quarter comparison | [Learn → Time Comparisons](/as-code/aql/learn/time-comparisons), [Cookbook → Period Comparison](/as-code/aql/cookbook/aql-period-comparison) |
| Smooth a time series with a moving average | [Cookbook → Moving Average](/as-code/aql/cookbook/aql-moving-average) |
| Compound annual growth rate (CAGR) | [Cookbook → CAGR](/as-code/aql/cookbook/aql-period-comparison#method-5-compound-annual-growth-rate-cagr) |
| Analyze customer order frequency / cohort distributions | [Cookbook → Customer Order Frequency](/as-code/aql/cookbook/aql-customer-order-frequency) |
## By metric shape
Most metric questions resolve once you answer two questions:
1. **One aggregation, or several?** A single `sum`/`count`/`avg` is simple aggregation. Anything that aggregates an already-aggregated value (avg of monthly totals, percent of total, semi-additive sums) is multi-aggregation.
2. **What's the relationship between aggregations or filters?** Conditions, time periods, subgroups, accumulation, or nesting each map to a different AQL function.
### Single-aggregation metrics
| Shape | Example | Where to go |
|---|---|---|
| Multiple tables/models | `order_items \| sum(order_items.quantity * products.price)` | [Cross-Model Queries](/as-code/aql/learn/cross-model) |
| Filtered by condition | `avg(order_items.quantity) \| where(order_items.created_at matches @(last 3 months))` | [where()](/reference/aql/where) + [logical operators](/reference/aql/operator#logical-operator) |
| Running / accumulated | `orders.total \| running_total(orders.created_at \| year())` | [Cumulative Metrics](/as-code/aql/cookbook/aql-cumulative-metrics), [window_sum](/reference/aql/window_sum) |
| Different time period | `orders.count \| relative_period(orders.created_at, interval(-1 year))` | [Period Comparison](/as-code/aql/cookbook/aql-period-comparison) |
### Multi-aggregation metrics
| Shape | Example | Where to go |
|---|---|---|
| Scalar combination of metrics | `sum(products.price) / count(products.id)` | Just write `metric_a / metric_b` |
| Aggregations linked by a condition | `sum(balances.bank_balance) \| where(dim_dates.date == max(balances.record_date))` | [Semi-Additive Calculation](/as-code/aql/cookbook/aql-semi-additive-calculation) |
| Calculated across different subgroups | `(order_items.total_sales*1.0) / (order_items.total_sales \| of_all(order_items))` | [Level of Detail Patterns](/as-code/aql/cookbook/level-of-detail), [Percent of Total](/as-code/aql/cookbook/aql-percent-of-total) |
| Nested aggregations | `users \| group(month(users.sign_up_at)) \| select(count(users.id)) \| avg()` | [Nested Aggregation](/as-code/aql/cookbook/aql-nested-aggregation) |
## Snippet gallery
Copy-paste-able definitions for the most common patterns.
### Simple aggregation
Simple aggregation works by taking a table and an expression to evaluate over each row of that table.
```js title="Total Price of all Products after Discount"
// `products` source table expression can be omitted
products | sum(products.price * products.discount)
```
```js title="Average Ordered Quantity of Order Items"
avg(order_items.quantity)
```
### Conditional aggregation
```js title="Average Ordered Quantity of Order Items over the Last 3 Months"
avg(order_items.quantity)
| where(order_items.created_at matches @(last 3 months))
```
### Aggregation with scalar functions
```js title="Average Price of Product"
sum(products.price) / count(products.id)
```
```js title="Total Actual Product Price"
products | sum(products.price * products.discount)
```
### Cross-model aggregation
```js title="Gross Merchandise Value (GMV)"
order_items | select(order_items.quantity * products.price) | sum()
// or more succinctly
order_items | sum(order_items.quantity * products.price)
```
```js title="GMV of refunded orders"
order_items
| sum(order_items.quantity * products.price)
| where(orders.status != 'refunded')
```
See [Cross-Model Queries](/as-code/aql/learn/cross-model) for the full walkthrough.
### Cumulative metrics
```js title="Cumulative Sum of GMV"
// orders.value = order_items | sum(order_items.quantity * products.price)
sum(orders.value) | running_total()
```
```js title="Running Percentage of Asia GMV over global GMV"
(sum(orders.value) | running_total() | where(continents.name == 'Asia'))
/ (sum(orders.value) | running_total())
```
See [Cumulative Metrics](/as-code/aql/cookbook/aql-cumulative-metrics) for the full walkthrough.
### Window functions
```js title="Running Sum of Count over Order Status"
window_sum(count(orders.id), order: orders.status)
```
### Multiple aggregation levels
```js title="Average GMV per Customer"
orders | group(users.id) | select(sum(orders.value)) | avg()
```
See [Nested Aggregation](/as-code/aql/cookbook/aql-nested-aggregation).
### Custom relationships
```js title="Sum of revenue using custom relationships"
sum(order_items.revenue)
| with_relationships(
order_items.order_id > orders.id,
order_items.country_id > countries.id,
)
```
See [`with_relationships`](/reference/aql/with_relationships).
### Semi-additive metrics
```js title="Sum Bank Balance Any Customers"
sum(balances.bank_balance)
| where(dim_dates.date == (
max(balances.record_date) | of_all(balances.user_name)
))
```
See [Semi-Additive Calculation](/as-code/aql/cookbook/aql-semi-additive-calculation).
---
In Holistics, data exploration is typically done through the UI, which generates AQL queries in the [`explore { }`](/reference/aql/explore-expression) format. The examples here show AML metric definitions. In practice, you define metrics once in AML and the UI generates the explore syntax for you.