How Sidemantic Works
The mental model: automatic joins, automatic grouping, correctness with fan-out, and the compilation pipeline.
This page is the conceptual spine: if you remember one thing about Sidemantic, remember automatic joins and automatic grouping.
Core Objects
- Model: a named dataset (usually a table; can also be a SQL subquery) with a
primary_key. - Dimension: a field you can group/filter by (categorical, numeric, boolean, time).
- Metric (model-level): an aggregation defined on a single model (sum/count/avg/etc).
- Metric (graph-level): a metric defined as a formula over other metrics.
- Segment: a named filter you can reuse in queries.
- Relationship: declares how two models connect (many-to-one, one-to-many, many-to-many).
- Pre-aggregation: a materialized rollup table the planner can route queries to.
Query Semantics (Non-Negotiables)
Sidemantic SQL is not generic SQL.
- No
JOINkeyword: joins are inferred from referenced fields and declared relationships. GROUP BYis ignored: grouping is derived from the selected dimensions.DISTINCTis not supported: dimensions are treated as distinct at the query grain.
Automatic Joins
You trigger joins by referencing fields from multiple models in the same query.
Join inference relies on:
- relationship types (many-to-one vs one-to-many)
- declared keys (foreign keys + primary keys)
- choosing a join path when multiple paths exist (see Gotchas)
Automatic Grouping (Why GROUP BY is Ignored)
Sidemantic treats metrics as aggregations and dimensions as the grouping keys.
When you write:
SELECT customers.region, orders.revenue
FROM orders
Sidemantic interprets that as: “aggregate orders.revenue grouped by customers.region”.
Fan-out and Correctness
Fan-out happens when you join one row to many rows (e.g. orders → order_items).
Naive SQL sum(orders.amount) would double count.
Sidemantic uses symmetric aggregates to protect metric correctness in fan-out joins (see Fan-out & Symmetric Aggregates).
Compilation Pipeline
High-level stages:
- Parse semantic SQL (models + fields).
- Resolve join graph using relationships.
- Plan metrics (aggregation, filters, symmetric aggregates if needed).
- Generate SQL for the target engine/dialect.
Where Engine Differences Show Up
- SQL dialect differences (date functions, casts, identifiers)
- pre-aggregation materialization and routing behavior
- server/connectivity behavior (
serve) and adapter capabilities