Composability in metric views
This page explains how composability works in metric views and provides examples that show you how to compose logic by building on dimensions, measures, and joins within a single view.
Overview
Metric views are composable, which means you can define layered, reusable logic. Instead of writing every definition from scratch, you can create new ones that build on existing dimensions and measures.
With composability, you can:
- Reference previously defined dimensions in new dimensions
- Reference any dimension or previously defined measures in new measures
- Reference columns from joins defined in the metric view
Composability helps you avoid duplication, streamline metric definitions, and support more complex analysis without requiring raw SQL each time.
Metric composability
Composability is the principle of building complex metrics by reusing simpler, foundational measures. Instead of writing and maintaining complex, nested SQL logic for every derived KPI, you define the core "atomic" measures once and then reference them in other, more sophisticated calculations. This approach dramatically improves consistency, auditability, and maintenance of your semantic layer.
The foundation of composability is the MEASURE() function, which allows a measure definition to reference any other measure defined within the same metric view.
Define measures with composability
Composability is implemented in the measures section of the metric view YAML.
Measure Type | Description | Example |
|---|---|---|
Atomic | A simple, direct aggregation on a source column. These form the building blocks. |
|
Composed | An expression that mathematically combines one or more other measures using the |
|
Example: Average Order Value (AOV)
To calculate Average Order Value (AOV), you need two measures: Total Revenue and Order Count.
source: samples.tpch.orders
measures:
# Total Revenue
- name: total_revenue
expr: SUM(o_totalprice)
comment: The gross total value of all orders.
display_name: 'Total Revenue'
# Order Count
- name: order_count
expr: COUNT(1)
comment: The total number of line items or orders.
display_name: 'Order Count'
# Composed Measure: Average Order Value (AOV)
- name: avg_order_value
# Defines AOV as Total Revenue divided by Order Count
expr: MEASURE(total_revenue) / MEASURE(order_count)
comment: Total revenue divided by the number of orders.
display_name: 'Avg Order Value'
In this example, if the definition of total_revenue changes (e.g., if a filter to exclude tax is added), the avg_order_value automatically inherits that change, ensuring the AOV metric remains consistent with the new business rule.
Composability with conditional logic
You can use composability to create complex ratios, conditional percentages, and growth rates without relying on window functions for simple period-over-period calculations.
Example: Fulfillment Rate
To calculate the Fulfillment Rate (Fulfilled Orders / Total Orders), you first define the measure for completed orders using a FILTER clause.
source: samples.tpch.orders
measures:
# Total Orders (denominator)
- name: total_orders
expr: COUNT(1)
comment: Total volume of orders regardless of status.
# Fulfilled Orders (numerator)
- name: fulfilled_orders
expr: COUNT(1) FILTER (WHERE o_orderstatus = 'F')
comment: Only includes orders marked as fulfilled.
# Composed Measure: Fulfillment Rate (Ratio)
- name: fulfillment_rate
expr: MEASURE(fulfilled_orders) / MEASURE(total_orders)
display_name: 'Order Fulfillment Rate'
format:
type: percentage # Using semantic metadata to format as a percent
Best practices for using composability
- Define atomic measures first: Always establish your fundamental measures (
SUM,COUNT,AVG) before defining any measures that reference them. - Use
MEASURE()for consistency: Always use theMEASURE()function when referencing another measure's calculation within anexpr. Don't try to manually repeat the aggregation logic (for example, avoidSUM(a) / COUNT(b)if measures for both the numerator and denominator already exist). - Prioritize readability: The
exprfor a composed measure should read like a mathematical formula for the KPI. For example,MEASURE(Gross Profit) / MEASURE(Total Revenue)is clearer and easier to audit than a single complex SQL expression. - Combine with semantic metadata: After composing a ratio, use semantic metadata (as shown in the
fulfillment_rateexample) to automatically format the result as a percentage or currency for downstream tools. See Use semantic metadata in metric views.