Use case
Average order value (AOV) — sometimes called basket size — is revenue divided by the number of orders. It looks like a one-line calculation, but where the two parts live decides how it is modeled:- Same cube — both parts are measures of one fact table.
- Two fact tables — revenue is aggregated at one grain (say, day/item/location) and orders are counted at another (transaction lines). This is the common shape in retail models.
amount / orders expression.
Same cube
When both parts are measures of the same cube, define AOV as a calculated measure that divides them:NULLIF guards the division so a group with no orders returns NULL rather
than failing.
Across two fact tables
Retail models usually split the two parts. Sales dollars come from a pre-aggregated daily table (item_location_sales, one row per day, item and
location), while the transaction count comes from the line-item table
(sales_line_item, one row per transaction line). The two never join to each
other — they meet through shared items, locations and dates cubes, which
makes this a multi-fact query.
1. Define each part on the cube that owns it
The denominator counts distinct transactions and excludes exchanges and non-store channels. Write that logic once, as measurefilters on the line-item cube, so every consumer picks
it up by including the measure — never restate it per view:
items, locations and dates cubes. The dates
spine matters: without it the two facts have no common time member to group by,
since one is keyed by day and the other by timestamp.
2. Define AOV on the view
Neither cube can define AOV — neither can reference the other’s measures. Define it as a measure of the view and mark itmulti_stage:
date, department
and region are common to both facts and can be grouped by.
3. Query it
Queryingaov_basket by region aggregates each fact on its own, stitches the
two results on the shared dimension, and takes the division over the joined rows:
multi_stage: true is what defers the division until both facts have been
aggregated. Without it, Cube plans the expression as an ordinary calculated
measure, looks for a single join tree covering both fact cubes, and fails with
Can't find join path to join 'locations', 'item_location_sales', 'sales_line_item'.