Dimensions are everything a metric can be grouped or filtered by: a status, a country, an order date.
In the latest YAML spec a dimension is a property of the column it comes from. There are two types,
categorical and time, and time dimensions also need the finest grain of the column.
Copy and paste
models:
- name: orders
semantic_model:
enabled: true
agg_time_dimension: order_date
columns:
- name: order_id
entity:
type: primary
name: order
- name: status
description: Order status from the shop system.
dimension:
type: categorical
name: order_status # optional: defaults to the column name
label: Order status # shown in BI tools
- name: order_date
granularity: day # on the column, not inside dimension
dimension:
type: time
- name: shipped_date
granularity: day
dimension:
type: time
Query them:
mf query --metrics revenue --group-by order__order_status
mf query --metrics revenue --group-by order__order_date__quarter
mf query --metrics revenue --group-by metric_time__month,order__order_status
order__order_status revenue
--------------------- ---------
shipped 2050
returned 180
Categorical dimensions
Any column you group or filter by that isn’t a key or a date: status, country, channel, a boolean flag.
The name defaults to the column name; set it when the column name is unclear, as with status above,
which becomes order_status. The description defaults to the column’s description, and label is what
BI tools display.
A column holds either an entity or a dimension, not both. A dimension’s name must be unique within its semantic model and must not repeat the name of an entity or a metric of the same model.
Time dimensions
A time dimension needs granularity, the finest grain the column holds: day for a date, hour or
finer for a timestamp. The key sits at the column level, next to name, not inside the dimension
block. The legacy type_params: time_granularity is deprecated.
At query time you can ask for the same grain or a coarser one, by adding it to the name:
order__order_date__week, __month, __quarter, __year. A finer grain than the column’s is refused:
order__order_date__hour on a day column returns “does not match any of the available group-by-items”.
metric_time or the dimension itself
Each semantic model has a default time dimension, agg_time_dimension, and every metric of the model is
counted by it. In queries that date is called metric_time, which is also the only time name that works
across metrics from different models. Use the dimension’s own name, such as order__shipped_date__month,
when you want to group by another date of the same rows. The difference between the two is covered in
how to set the default time dimension.
Dimensions from expressions
A dimension can’t have an expr. To compute one, such as an order size band, use derived_semantics;
see how to define a dimension from a SQL expression.
Partitioned dates
is_partition: true on a time dimension marks it as the partition date of a date-partitioned table. When
a query joins metrics from several tables, MetricFlow then matches the partitions instead of joining across
all dates.
Tested with dbt Core 1.12 and MetricFlow 0.213 on DuckDB.