To create Databricks metric views, write a YAML definition with a source, optional joins and filter, fields and measures, then save it with CREATE VIEW ... WITH METRICS LANGUAGE YAML or build it in the Catalog Explorer editor. You need SELECT on the source, CREATE TABLE and USE SCHEMA on the target schema, and compute on Databricks Runtime 16.4 or above. Anyone with SELECT then queries each measure through the MEASURE() function.
What do you need before you create a Databricks metric view?
A metric view is a Unity Catalog object that keeps measure definitions apart from the fields you group and filter by. A standard view fixes its aggregation at creation; a metric view lets a user group revenue per customer by any field at query time (Unity Catalog metric views).
Check four permissions first (Create a metric view):
SELECTon the source table, view or SQL query.CREATE TABLEandUSE SCHEMAon the schema that will hold the metric view.USE CATALOGon the parent catalog.CAN USEon a SQL warehouse or cluster.
Then check your runtime. Metric views arrived in Databricks Runtime 16.4, and later features need later runtimes (Metric view feature availability). A SQL warehouse updates itself, so runtimes matter only on clusters.
| Databricks Runtime | What it adds |
|---|---|
| 16.4 | Metric views themselves: create, query, manage |
| 17.3 | Snowflake-schema joins, materialization, agent metadata (YAML 1.1), TEMPORARY metric views |
| 18.0 | BI compatibility mode, REFRESH MATERIALIZED VIEW |
| 18.1 | One-to-many joins, window offset, rely.at_most_one_match |
| 18.2 | Parameters, wildcard fields (YAML 1.1) |
| 19 | Derived column names, windows on a numeric index (YAML 1.1) |
How do you create a metric view in Catalog Explorer?
The UI editor builds the YAML for you. Databricks documents a sales example on samples.tpch.orders, a table present in every workspace (Create a metric view). The Create page gives Runtime 17.3 as the minimum for this example. The feature availability table lists rely.at_most_one_match at 18.1.
- Open the editor. Click Catalog, find
samples.tpch.orders, then click Create > Metric view. Name it, pick a catalog and schema, and click Create. The editor loads every source column as a field and adds a sampleCOUNT(*)measure. - Add a join. Select
samples.tpch.customer, name the joincustomer, set the conditionsource.o_custkey = customer.c_custkey, choose Many-to-one and tick At most one match. - Add a filter. Set
source.o_orderdate > '1990-01-01'. The filter applies to every query on the view. - Keep the fields you need. Delete the rest, then define Order Month with a month transform, Order Status with a
CASEexpression in Custom, and Market Segment from the joined table. - Add measures. Order Count is
COUNT(1), Total Revenue isSUM(source.o_totalprice), and Total Revenue per Customer isSUM(source.o_totalprice) / COUNT(DISTINCT source.o_custkey). - Save. Preview each field or measure, then click Save.
Genie Code, in the same editor, drafts a definition from a plain-language request (Create a metric view) or turns a Tableau or Power BI file into a metric view (Use metric views with external BI tools).
See where metric definitions sit in the AI context stack
A short brief on the layers of context that AI agents read, from metric definitions and lineage to policies.
Get the AI Context StackHow do you create a metric view with SQL and YAML?
Wrap the YAML in CREATE VIEW with the WITH METRICS clause and put it between $$ delimiters. Here is the documented statement for the sales example on samples.tpch.orders joined to samples.tpch.customer (Create a metric view):
CREATE OR REPLACE VIEW orders_metric_view WITH METRICS LANGUAGE YAML AS
$$
version: 1.1
comment: "Orders KPIs for sales analysis"
source: samples.tpch.orders
joins:
- name: customer
source: samples.tpch.customer
'on': source.o_custkey = customer.c_custkey
rely:
at_most_one_match: true
filter: source.o_orderdate > '1990-01-01'
fields:
- name: Order Month
expr: DATE_TRUNC('MONTH', source.o_orderdate)
comment: "Month of order"
- name: Order Status
expr: |-
CASE
WHEN source.o_orderstatus = 'O' THEN 'Open'
WHEN source.o_orderstatus = 'P' THEN 'Processing'
WHEN source.o_orderstatus = 'F' THEN 'Fulfilled'
END
comment: "Status of order"
- name: Market Segment
expr: customer.c_mktsegment
comment: "Customer market segment"
measures:
- name: Order Count
expr: COUNT(1)
comment: "Total number of orders"
- name: Total Revenue
expr: SUM(source.o_totalprice)
comment: "Sum of all order prices"
- name: Total Revenue per Customer
expr: SUM(source.o_totalprice) / COUNT(DISTINCT source.o_custkey)
comment: "Average revenue per unique customer"
$$
The YAML rules that trip people up (Metric view YAML syntax reference):
versionandsourceare required. You needfieldsormeasures, or both.sourcecan be a three-part table name, another metric view or a SQL query.- Every measure must use an aggregate function.
- Joins are many-to-one
LEFT OUTER JOINs by default.at_most_one_match: trueis not checked at runtime, so a fan-out join returns wrongSUMandCOUNTresults. - Wrap any expression that contains a colon, or starts with a backtick, in double quotes.
How do you query a Databricks metric view with MEASURE()?
On the orders_metric_view sales example, select fields by name and wrap every measure in MEASURE() (Query metric views):
SELECT
`Order Month`,
`Order Status`,
MEASURE(`Order Count`),
MEASURE(`Total Revenue`)
FROM orders_metric_view
GROUP BY ALL
ORDER BY `Order Month`;
SELECT * does not work, because each measure needs MEASURE(). On Runtime 18.1 and above, AGG() works as an alias. You cannot join a metric view directly to another table; aggregate it in a CTE first, then join the CTE.
DESCRIBE TABLE EXTENDED <catalog.schema.metric_view_name> AS JSON returns the stored YAML in View Text.
The same view feeds AI/BI dashboards, Genie Agents and alerts.
External BI tools connect through these routes (Use metric views with external BI tools):
| Route | How it works | Fits |
|---|---|---|
| Custom SQL | The tool sends the MEASURE() query as written |
Power BI native query in DirectQuery mode, Tableau Custom SQL, Sigma, most JDBC or ODBC tools |
| Wrapper view | A standard view wraps fixed MEASURE() columns |
Any tool that reads a Unity Catalog table; one view per dimension set |
| BI compatibility mode | Databricks rewrites the tool’s SUM and COUNT into measure logic |
Tableau, through the Initial SQL field |
| Built-in partner integration | The partner shows measures and dimensions natively, without custom SQL | Partners listed under Partner Connect |
Find the gaps in your metric context
Estimate how much of the context your teams and agents need is missing, and where.
Try the Context Gap CalculatorHow do you add synonyms, display names and materialization?
Agent metadata needs Runtime 17.3 and YAML version 1.1 (Agent metadata in metric views). It adds three things to each field or measure:
display_name, up to 255 characters, shown in dashboards instead of the column name.synonyms, up to 10 per field or measure, which Genie uses to match questions, so “total sales” findstotal_revenue.format, for number, currency, percentage, byte, date and date-time display.
Saving a version 1.1 definition strips # YAML comments, so move anything worth keeping into comment fields first.
Window measures handle rolling and cumulative values. The documented example counts unique customers over a trailing 7 days (Metric view YAML syntax reference):
version: 1.1
source: samples.tpch.orders
fields:
- name: order_date
expr: o_orderdate
measures:
- name: rolling_7day_customers
expr: COUNT(DISTINCT o_custkey)
display_name: '7-Day Rolling Customers'
window:
- order: order_date
range: trailing 7 day
Materialization speeds up queries by pre-computing aggregates. It needs serverless compute and Runtime 17.3 or above (Materialization for metric views). You add a materialization block with mode: relaxed, an optional schedule such as every 6 hours, and a list of aggregated or unaggregated materialized views. A managed Lakeflow pipeline builds them, and matching queries reroute automatically. Queries with no match read the source tables directly, so freshness can differ between two queries on the same view. Without materialization, every query recomputes from source, a cost Daniel Beach calls out in his walkthrough of metric views.
Plan for these limits before you materialize:
- No materialization when the view or a source uses row filters, column masks or ABAC policies.
COUNT(DISTINCT)and window measures serve exact-match queries only, never rollups.- Without a schedule, refresh by hand with
REFRESH MATERIALIZED VIEW <metric-view-name>.
How do you grant access to and edit a metric view?
A metric view follows the Unity Catalog permission model, so users who already hold SELECT on the parent catalog or schema can query it, because privileges cascade (Manage metric views). To grant one group query access:
GRANT SELECT ON orders_metric_view to `data-consumers`;
Only the owner can edit the definition. In SQL, ALTER VIEW with the complete YAML replaces the definition. For team editing, grant a group SELECT on every source table and transfer ownership to it. Group ownership does not work for materialized metric views.
A DROP VIEW cannot be undone, so check the Lineage tab for dashboards and notebooks that read the view first. Sharing a metric view with another metastore through OpenSharing is in Beta.
Advancing Analytics advises one business area per metric view and only the joined attributes you need (Advancing Analytics step-by-step guide).
How does Atlan work with Databricks metric views?
Atlan’s Databricks connector catalogs each metric view as its own DatabricksMetricView asset. It records the view’s create statement as the asset definition, shown in the asset profile, and it includes metric views in lineage tracking (What does Atlan crawl from Databricks?). Upstream column lineage for individual dimensions and measures isn’t supported. Lineage from Databricks AI/BI dashboards to the metric views they read is in private preview (Extract Databricks dashboard lineage).
Atlan was a launch partner for Databricks Unity Catalog Metrics at the 2025 Data + AI Summit, and it enriches each metric with business context and end-to-end lineage (Atlan at Data + AI Summit 2025). It then serves those definitions back to Genie and to other agents through an MCP server, SQL and open APIs (Unity Catalog Metrics and the context layer).
General Motors built its Insight Factory on Databricks Unity Catalog and uses Atlan for end-to-end lineage. The GM team has brought time-to-insight down from 28 days to 3 hours (Databricks Unity Catalog with Atlan).
For the wider picture, see what Unity Catalog’s semantic layer covers and how a metrics catalog connects to Databricks.
Watch the WTF is the Context Layer series
Live sessions on how teams govern metric definitions, lineage and ownership for AI.
Register for the SeriesFAQs about Databricks metric views
Do Databricks metric views replace standard views?
No. A standard view still fits a fixed query with fixed groupings. A metric view fits a metric that people slice many ways, such as revenue by month, by segment or by region. It stores the measure once, and the engine computes it for whatever fields the query groups by.
What is the difference between fields and dimensions in a metric view?
None. fields and dimensions are equivalent keywords, and Databricks now documents fields as the preferred term. The Catalog Explorer editor labels the tab Fields but writes dimensions into the YAML. One exception: a materialization block must list dimensions: even when the top-level definition uses fields:.
Can you join a Databricks metric view to another table?
Not directly in the query. Joins belong inside the definition, under joins, where they run as left outer joins from the source. To combine metric view results with another table at query time, select the measures in a CTE with MEASURE() and GROUP BY, then join the CTE to the other table.
Why does SELECT * fail on a metric view?
Every measure must be evaluated through the MEASURE() aggregate function, and SELECT * cannot apply it. List each field by name and wrap each measure, for example MEASURE(`Total Revenue`), then add GROUP BY ALL. On Runtime 18.1 and above, AGG() is an accepted alias for MEASURE().
How do you change a metric view after you create it?
The owner edits it in Catalog Explorer, through the UI tab or the YAML editor, or runs ALTER VIEW with the complete new YAML. ALTER VIEW replaces the whole definition and drops Unity Catalog comments that are not in the YAML comment fields. Wildcard fields expand at creation, so recreate the view to pick up new source columns.
Sources
- Create a metric view, Azure Databricks documentation on Microsoft Learn
- Query metric views, Azure Databricks documentation on Microsoft Learn
- Unity Catalog metric views, Azure Databricks documentation on Microsoft Learn
- Metric view feature availability, Azure Databricks documentation on Microsoft Learn
- Use metric views with external BI tools, Azure Databricks documentation on Microsoft Learn
- Metric view YAML syntax reference, Azure Databricks documentation on Microsoft Learn
- Agent metadata in metric views, Azure Databricks documentation on Microsoft Learn
- Materialization for metric views, Azure Databricks documentation on Microsoft Learn
- Manage metric views, Azure Databricks documentation on Microsoft Learn
- Databricks Semantic Layer: Metric Views, Daniel Beach, Data Engineering Central
- How to Build a Metric View in Databricks: A Step-by-Step Guide for Analysts, Advancing Analytics
- What does Atlan crawl from Databricks?, Atlan documentation
- Extract Databricks dashboard lineage, Atlan documentation