<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Metric Views in Warehousing &amp; Analytics</title>
    <link>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135717#M2290</link>
    <description>&lt;P&gt;Incredible, thanks very much Louis!&lt;/P&gt;</description>
    <pubDate>Wed, 22 Oct 2025 14:57:20 GMT</pubDate>
    <dc:creator>playnicekids</dc:creator>
    <dc:date>2025-10-22T14:57:20Z</dc:date>
    <item>
      <title>Metric Views</title>
      <link>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135694#M2288</link>
      <description>&lt;P&gt;Hi&lt;/P&gt;&lt;P&gt;I think I’ve found a reproducible bug / or am misunderstanding some syntax / capabilities of Metric Views when joining a calendar scaffold to an SCD2 table.&lt;BR /&gt;The same SQL query works perfectly, but the Metric View always returns a constant 1 per month when using COUNT(DISTINCT …) on a joined column. I've added some simple code / metric view that reproduces the behaviour I'm seeing.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Minimal Repro Code:&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;-- Base calendar&lt;BR /&gt;CREATE OR REPLACE TABLE dim_calendar_month AS&lt;BR /&gt;SELECT explode(sequence(DATE'2025-06-01', DATE'2025-08-01', INTERVAL 1 MONTH)) AS month_start,&lt;BR /&gt;last_day(month_start) AS month_end;&lt;/P&gt;&lt;P&gt;-- Simple SCD2 table&lt;BR /&gt;CREATE OR REPLACE TABLE dim_contact AS VALUES&lt;BR /&gt;('A','Open','client',DATE'2024-01-01',NULL),&lt;BR /&gt;('B','Open','client',DATE'2025-06-01',DATE'2025-07-01'),&lt;BR /&gt;('B','Closed','client',DATE'2025-07-01',NULL),&lt;BR /&gt;('D','Open','client',DATE'2025-07-15',NULL)&lt;BR /&gt;AS dim_contact(contact_id,status,contact_type,from_date,to_date);&lt;/P&gt;&lt;P&gt;-- Works fine (expected 2,2,2)&lt;BR /&gt;WITH calendar_cte AS (SELECT month_start, month_end FROM dim_calendar_month)&lt;BR /&gt;SELECT calendar_cte.month_end, COUNT(DISTINCT c.contact_id) AS open_contacts&lt;BR /&gt;FROM calendar_cte&lt;BR /&gt;LEFT JOIN dim_contact c&lt;BR /&gt;ON c.from_date &amp;lt;= calendar_cte .month_end&lt;BR /&gt;AND (c.to_date &amp;gt; calendar_cte .month_end OR c.to_date IS NULL)&lt;BR /&gt;AND lower(c.status)='open'&lt;BR /&gt;GROUP BY calendar_cte .month_end&lt;BR /&gt;ORDER BY calendar_cte .month_end;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Metric View:&lt;/STRONG&gt;&lt;/P&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;version: 1.1&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;source: MY_CATALOG&lt;/SPAN&gt;&lt;SPAN&gt;.mv_bug_demo.dim_calendar_month&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;joins:&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;contact&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; source:&lt;/SPAN&gt;&lt;SPAN&gt;mv_bug_demo.dim_contact&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; "on": &lt;/SPAN&gt;&lt;SPAN&gt;contact.from_date &amp;lt;= source.month_end AND (contact.to_date &amp;gt; source.month_end&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;OR contact.to_date IS NULL) AND lower(contact.status) = 'open' AND contact.contact_type&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;= 'client'&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;dimensions:&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;month&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;source.month_end&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; display_name: &lt;/SPAN&gt;&lt;SPAN&gt;Month&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;contact_id&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;contact.contact_id&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; display_name: &lt;/SPAN&gt;&lt;SPAN&gt;Contact ID&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;measures:&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;eligible_contacts&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;COUNT(DISTINCT contact_id)&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; display_name: &lt;/SPAN&gt;&lt;SPAN&gt;Eligible Contacts&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;rows_all&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;COUNT(*)&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;contacts_distinct&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;COUNT(DISTINCT contact.contact_id)&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;dup_rows&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;MEASURE(rows_all) - MEASURE(contacts_distinct)&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; - name: &lt;/SPAN&gt;&lt;SPAN&gt;max_age&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &amp;nbsp; expr: &lt;/SPAN&gt;&lt;SPAN&gt;MAX(contact.age)&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;P&gt;&lt;STRONG&gt;SQL:&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;-- Returns 1, 1, 1&lt;/P&gt;&lt;DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;SELECT&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;month&lt;/SPAN&gt;&lt;SPAN&gt;,&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN&gt;MEASURE&lt;/SPAN&gt;&lt;SPAN&gt;(eligible_contacts) &lt;/SPAN&gt;&lt;SPAN&gt;AS&lt;/SPAN&gt;&lt;SPAN&gt; eligible_contacts&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;FROM&lt;/SPAN&gt;&lt;SPAN&gt; dim_calendar_month_metric_view&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;GROUP BY&lt;/SPAN&gt; &lt;SPAN&gt;month&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;ORDER BY&lt;/SPAN&gt; &lt;SPAN&gt;month&lt;/SPAN&gt;&lt;SPAN&gt;;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;H4&gt;Environment&lt;/H4&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Unity Catalog enabled&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Runtime: 16.0&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;DBSQL metric view syntax: version 1.1&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 22 Oct 2025 12:53:29 GMT</pubDate>
      <guid>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135694#M2288</guid>
      <dc:creator>playnicekids</dc:creator>
      <dc:date>2025-10-22T12:53:29Z</dc:date>
    </item>
    <item>
      <title>Re: Metric Views</title>
      <link>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135716#M2289</link>
      <description>&lt;P&gt;Hey&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/193456"&gt;@playnicekids&lt;/a&gt;&amp;nbsp;, I dig some digging and have come up with some helpful hints/tips to get you past your issue:&lt;/P&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;This behavior is due to how metric view joins are defined and executed.&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;H3 class="paragraph"&gt;Diagnosis&lt;/H3&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;The join in your metric view is a many-to-many temporal join (calendar month → multiple open contact rows). Metric view joins are intended to be many-to-one; when they encounter many-to-many, the engine selects only the first matching row from the joined table for each source row. That collapses your month-to-contacts result to a single match per month, so COUNT(DISTINCT contact_id) returns 1 for every month.&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;This difference explains why your raw SQL works (it produces the cartesian month–contact set) while the metric view does not (it reduces the join to one match per source row).&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;Two additional notes that are relevant to your setup: * Metric views can use a SQL query as the &lt;STRONG&gt;source&lt;/STRONG&gt;, which is the recommended way to handle many-to-many expansions like calendar scaffolds, because the expansion happens inside the source rather than in the metric view join layer.&lt;/DIV&gt;
&lt;UL&gt;
&lt;LI&gt;Metric views don’t support adding new joins at query time; the join semantics must be modeled in the view definition or the view’s source SQL. Using a pre-expanded SQL source avoids this limitation while preserving correct DISTINCT semantics.&lt;/LI&gt;
&lt;/UL&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;H3 class="paragraph"&gt;Fix Options&lt;/H3&gt;
&lt;DIV class="paragraph"&gt;Pick one of the following approaches to get correct counts.&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;H4 class="paragraph"&gt;Option A:&lt;/H4&gt;
&lt;DIV class="paragraph"&gt;Push the temporal join into the source SQL Define the metric view over a SQL query that enumerates month–contact pairs (the same logic you used in plain SQL). This keeps the many-to-many expansion out of the metric view’s join semantics and preserves correct COUNT(DISTINCT) results.&lt;/DIV&gt;
&lt;PRE&gt;&lt;CODE class="markdown-code-sql"&gt;-- Metric view definition (YAML in SQL)
ALTER VIEW my_catalog.mv_bug_demo.dim_calendar_month_metric_view AS
version: 1.1
source: |
  SELECT
    m.month_end AS month,
    c.contact_id
  FROM my_catalog.mv_bug_demo.dim_calendar_month m
  LEFT JOIN my_catalog.mv_bug_demo.dim_contact c
    ON c.from_date &amp;lt;= m.month_end
   AND (c.to_date &amp;gt; m.month_end OR c.to_date IS NULL)
   AND lower(c.status) = 'open'
   AND c.contact_type = 'client'
dimensions:
  - name: month
    expr: month
    display_name: Month

  - name: contact_id
    expr: contact_id
    display_name: Contact ID

measures:
  - name: eligible_contacts
    expr: COUNT(DISTINCT contact_id)
    display_name: Eligible Contacts&lt;/CODE&gt;&lt;/PRE&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;Query: &lt;CODE&gt;sql
SELECT
  month,
  MEASURE(eligible_contacts) AS eligible_contacts
FROM my_catalog.mv_bug_demo.dim_calendar_month_metric_view
GROUP BY month
ORDER BY month;
&lt;/CODE&gt;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;This reproduces your working SQL result (2, 2, 2) because the source is already at the month–contact grain, and COUNT(DISTINCT contact_id) is evaluated correctly at the month grouping.&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;H4 class="paragraph"&gt;Option B:&lt;/H4&gt;
&lt;DIV class="paragraph"&gt;Materialize a helper view and use it as the source If you prefer to keep the metric view YAML simpler, create a view that precomputes the scaffolding and then point the metric view at it.&lt;/DIV&gt;
&lt;PRE&gt;&lt;CODE class="markdown-code-sql"&gt;CREATE OR REPLACE VIEW my_catalog.mv_bug_demo.v_month_contact_open AS
SELECT
  m.month_end AS month,
  c.contact_id
FROM my_catalog.mv_bug_demo.dim_calendar_month m
LEFT JOIN my_catalog.mv_bug_demo.dim_contact c
  ON c.from_date &amp;lt;= m.month_end
 AND (c.to_date &amp;gt; m.month_end OR c.to_date IS NULL)
 AND lower(c.status) = 'open'
 AND c.contact_type = 'client';&lt;/CODE&gt;&lt;/PRE&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;Metric view (YAML): &lt;CODE&gt;yaml
version: 1.1
source: my_catalog.mv_bug_demo.v_month_contact_open
dimensions:
  - name: month
    expr: month
    display_name: Month
  - name: contact_id
    expr: contact_id
    display_name: Contact ID
measures:
  - name: eligible_contacts
    expr: COUNT(DISTINCT contact_id)
    display_name: Eligible Contacts
&lt;/CODE&gt;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;Query: &lt;CODE&gt;sql
SELECT month, MEASURE(eligible_contacts)
FROM my_catalog.mv_bug_demo.dim_calendar_month_metric_view
GROUP BY month
ORDER BY month;
&lt;/CODE&gt;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;Same correct result, with the expansion done in the view rather than in the metric view join.&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;H4 class="paragraph"&gt;Why the original metric view returns 1&lt;/H4&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;Metric view joins are designed for star/snowflake schema where the source fact joins to dimensions in a many-to-one relationship. In many-to-many cases (like calendar scaffolds), metric views pick the first matching row from the joined table for each source row; that’s why you see a single joined contact per month and a constant COUNT(DISTINCT contact_id) = 1.&lt;/DIV&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;H3 class="paragraph"&gt;Small correctness tips&lt;/H3&gt;
&lt;UL&gt;
&lt;LI class="paragraph"&gt;You already quoted the “on” key in YAML; that’s important because YAML 1.1 parsers can misinterpret unquoted “on” as a boolean and break joins.&lt;/LI&gt;
&lt;LI&gt;When consuming metric views, make sure the attached compute meets the supported runtime requirement (Databricks Runtime 16.4+ for querying metric views), even though your simple query may still run on earlier versions.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hope this helps, Louis.&lt;/P&gt;
&lt;DIV class="paragraph"&gt;&amp;nbsp;&lt;/DIV&gt;</description>
      <pubDate>Wed, 22 Oct 2025 14:51:15 GMT</pubDate>
      <guid>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135716#M2289</guid>
      <dc:creator>Louis_Frolio</dc:creator>
      <dc:date>2025-10-22T14:51:15Z</dc:date>
    </item>
    <item>
      <title>Re: Metric Views</title>
      <link>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135717#M2290</link>
      <description>&lt;P&gt;Incredible, thanks very much Louis!&lt;/P&gt;</description>
      <pubDate>Wed, 22 Oct 2025 14:57:20 GMT</pubDate>
      <guid>https://community.databricks.com/t5/warehousing-analytics/metric-views/m-p/135717#M2290</guid>
      <dc:creator>playnicekids</dc:creator>
      <dc:date>2025-10-22T14:57:20Z</dc:date>
    </item>
  </channel>
</rss>

