What is a semantic view?¶
A semantic view is a database object that sits on top of your raw tables and
defines business metrics and dimensions in one governed place. Instead of every
analyst writing their own SUM(revenue) query and hoping the numbers agree,
the warehouse stores the definition once and everyone queries the same source of
truth.
How warehouses implement them¶
Snowflake calls them semantic views. You create one with CREATE SEMANTIC VIEW, declaring measures, dimensions, and relationships over your physical tables. The view generates SQL at query time based on which fields are requested.
Databricks calls them metric views. You define one with CREATE OR REPLACE VIEW … WITH METRICS LANGUAGE YAML, whose YAML body lists metrics (with aggregation functions) and dimensions. The concept is the same: a single definition that produces consistent numbers across queries.
DuckDB implements semantic views through the community
semantic_views extension.
You create them with CREATE SEMANTIC VIEW, declaring metrics, dimensions,
and facts over a source table. At query time, DuckDB uses a semantic_view()
table function instead of a direct SELECT from the view:
SELECT "revenue" AS "revenue", "country" AS "country"
FROM semantic_view('sales', dimensions := ['country'], metrics := ['revenue'])
The function takes the view name and named keyword lists for the fields to query. Semolina generates this syntax when the registered dialect is DuckDB.
All three approaches share a goal: make business metrics self-service and trustworthy by centralizing the logic in the warehouse.
Why you cannot select from one like a table¶
A semantic view stores a metric as a definition, not as a column. revenue
is the recipe SUM(s.revenue), and the warehouse only computes it once you
say which dimensions to group by. So SELECT revenue FROM sales does not mean
anything: there is no column to read. You have to ask for the metric through the
operator that tells the warehouse “evaluate this definition here”.
Each warehouse spells that operator differently, and this is the single biggest surface difference between the three:
Warehouse |
Asking for a metric |
Asking for a dimension |
|---|---|---|
Snowflake |
|
|
Databricks |
|
|
DuckDB |
|
|
Snowflake and Databricks keep the familiar SELECT ... FROM view shape and
change what may appear in the select list. DuckDB changes the shape instead: you
select from a semantic_view() table function and pass the field names as
lists, so there is no per-metric operator at all.
This is why Semolina exists as more than a convenience. You write
.metrics(Sales.revenue).dimensions(Sales.country) once, and the dialect for
the registered engine decides whether that becomes AGG(), MEASURE() or a
keyword list. The query builder shows the generated SQL
for all three side by side.
Left alone, the difference would reach the column names that come back too:
Snowflake would name the column AGG("REVENUE"). Semolina aliases each
selected column to its field name (AGG("REVENUE") AS "revenue"), so a
result row’s keys are your model’s field names on every backend. See
How result columns are named for that, and
Developing on DuckDB, deploying elsewhere for the behaviours that still differ once
you move off a local DuckDB.
Where Semolina fits¶
Semolina mirrors your warehouse semantic views as typed Python models. Each model
is a Python class with Metric and
Dimension fields that correspond to the measures and
dimensions defined in your warehouse. A
third field type, Fact, lets you mark raw event-level numerics
separately from categorical dimensions – see How to define models.
This gives you:
IDE autocomplete on field names, rather than column names typed into raw SQL
Type safety at the model level (metrics and dimensions are distinct types)
Backend-agnostic queries – write once, run against Snowflake, Databricks, or DuckDB by changing the connection config
Semolina does not replace your warehouse definitions. It reads from them. You define the semantic view in your warehouse, then create a matching Semolina model in Python. The codegen CLI can generate these models for you.
See also¶
Snowflake: CREATE SEMANTIC VIEW – Snowflake’s semantic view documentation
Databricks: CREATE VIEW … WITH METRICS – Databricks’ metric view documentation
Installation – get started with Semolina
Your first query – define a model and run a query
How to define models – field types and model configuration
How to configure your warehouse backend – Snowflake, Databricks, and DuckDB connection details
How result columns are named – what the columns are called when the results come back
Developing on DuckDB, deploying elsewhere – what a DuckDB-only test suite cannot tell you