A Semantic Query is a structured object — metrics × dimensions × filters × grain. Every consumer emits the same shape; the compiler turns it into correct, dialect-specific SQL.
"metrics": ["average_order_value"],
"dimensions": ["customer.region"],
"grain": "month",
"filters": [
"field": "order.status",
"op": "=", "value": "paid"
],
"order": ["month"],
"limit": 100
// no joins. no aggregation.
// no dialect. no rollup names. -- fan-out-safe · Join Graph resolved
-- served from a covering rollup
SELECT
date_trunc('month', o.order_date) AS month,
c.region,
SUM(o.amount) / NULLIF(COUNT(o.id),0)
AS average_order_value
FROM rollup_orders o
JOIN dim_customer c
ON o.customer_key = c.customer_key
WHERE o.status = 'paid'
GROUP BY 1, 2
ORDER BY 1
LIMIT 100; average_order_value is a Metric — a ratio of two Measures computed after aggregation, not avg(amount). region lives on Customer; the compiler walks Order → Customer to reach it. You just listed them.
The compiler is one half of the story — the hot path serving this from a rollup instead of the warehouse is the other.