All skills
dbt-labs avatar

/building-dbt-semantic-layer

@f8d7828 official
by dbt Labsdbt-labs/dbt-agent-skills729 stars
62

Use when creating or modifying dbt Semantic Layer components — semantic models, metrics, dimensions, entities, measures, or time spines. Covers MetricFlow configuration, metric types (simple, derived, cumulative, ratio, conversion), and validation for both latest and legacy YAML specs.

Use this Skill: https://skilld.dev/gh/dbt-labs/dbt-agent-skills/building-dbt-semantic-layer

This session only. Nothing lands on disk.

referencestime-spine.md

≈1.4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Add Time Spine for MetricFlow Semantic Layer

Overview

A time spine is essential for time-based joins and aggregations in MetricFlow. It provides the foundation for time-based metrics and dimensions.

When to Use

  • Setting up a new dbt semantic layer project
  • MetricFlow errors about missing time spine
  • Adding time-based grouping to metrics
  • Creating cumulative or time-window metrics

Steps to Add Time Spine

1. Create the Time Spine Model

Create models/marts/time_spine_daily.sql.

Using dbt.date_spine macro (when supported by your adapter):

{{
    config(
        materialized = 'table',
    )
}}

with

base_dates as (
    {{
        dbt.date_spine(
            'day',
            "DATE('2000-01-01')",
            "DATE('2030-01-01')"
        )
    }}
),

final as (
    select
        cast(date_day as date) as date_day
    from base_dates
)

select *
from final
where date_day > dateadd(year, -5, current_date())
  and date_day < dateadd(day, 30, current_date())

Note: dbt.date_spine() is not available for all adapters. If the macro isn't supported, use raw SQL with generate_series or your warehouse's equivalent date generation function instead.

2. Configure YAML for MetricFlow

Create models/marts/_models.yml:

models:
  - name: time_spine_daily
    description: A time spine with one row per day, ranging from 5 years in the past to 30 days into the future.
    time_spine:
      standard_granularity_column: date_day
    columns:
      - name: date_day
        description: The base date column for daily granularity
        granularity: day

3. Build and Validate

# Build the time spine table
dbt run --select time_spine_daily

# Preview the model
dbt show --select time_spine_daily

Query with metrics (if metrics are defined):

# Local development (MetricFlow CLI)
mf validate-configs
mf query --metrics <your_metric> --group-by metric_time

# dbt Studio / dbt Cloud / dbt Cloud CLI
dbt sl query --metrics <your_metric> --group-by metric_time

Using an Existing dim_date Model

If you have an existing date dimension model, configure it as a time spine:

models:
  - name: dim_date
    description: An existing date dimension model used as a time spine.
    time_spine:
      standard_granularity_column: date_day
    columns:
      - name: date_day
        granularity: day

Additional Granularities

Yearly Time Spine

Create models/marts/time_spine_yearly.sql:

{{
    config(
        materialized = 'table',
    )
}}

with years as (
    {{
        dbt.date_spine(
            'year',
            "to_date('01/01/2000','mm/dd/yyyy')",
            "to_date('01/01/2025','mm/dd/yyyy')"
        )
    }}
),

final as (
    select cast(date_year as date) as date_year
    from years
)

select * from final
where date_year >= date_trunc('year', dateadd(year, -4, current_timestamp()))
  and date_year < date_trunc('year', dateadd(year, 1, current_timestamp()))

Add to _models.yml:

models:
  - name: time_spine_yearly
    description: Time spine with one row per year
    time_spine:
      standard_granularity_column: date_year
    columns:
      - name: date_year
        granularity: year

Query with yearly granularity:

# Local development (MetricFlow CLI)
mf query --metrics orders --group-by metric_time__year

# dbt Studio / dbt Cloud / dbt Cloud CLI
dbt sl query --metrics orders --group-by metric_time__year

Custom Calendars (Fiscal Year)

Create models/marts/fiscal_calendar.sql:

with date_spine as (
    select
        date_day,
        extract(year from date_day) as calendar_year,
        extract(week from date_day) as calendar_week
    from {{ ref('time_spine_daily') }}
),

fiscal_calendar as (
    select
        date_day,
        case
            when extract(month from date_day) >= 10
                then extract(year from date_day) + 1
            else extract(year from date_day)
        end as fiscal_year,
        extract(week from date_day) + 1 as fiscal_week
    from date_spine
)

select * from fiscal_calendar

Add to _models.yml:

models:
  - name: fiscal_calendar
    description: A custom fiscal calendar with fiscal year and fiscal week granularities.
    time_spine:
      standard_granularity_column: date_day
      custom_granularities:
        - name: fiscal_year
          column_name: fiscal_year
        - name: fiscal_week
          column_name: fiscal_week
    columns:
      - name: date_day
        granularity: day
      - name: fiscal_year
        description: "Custom fiscal year starting in October"
      - name: fiscal_week
        description: "Fiscal week, shifted by 1 week from standard calendar"

Query with fiscal granularity:

# Local development (MetricFlow CLI)
mf query --metrics orders --group-by metric_time__fiscal_year

# dbt Studio / dbt Cloud / dbt Cloud CLI
dbt sl query --metrics orders --group-by metric_time__fiscal_year

Common Mistakes

Mistake Fix
Using semantic_models: instead of time_spine: Use the time_spine: property under models:
Missing standard_granularity_column Required property to tell MetricFlow which column to use
Missing granularity on columns Each time column needs a granularity: attribute

Reference

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides comprehensive guidance for authoring dbt Semantic Layer configurations across different specification versions. It includes best practices, implementation workflows, and validation steps using standard dbt tools and first-party utilities from dbt Labs. No security issues were detected.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    1/5 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at f8d7828. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 3 months ago
user-invocable
false
metadata
{
  "author": "dbt-labs"
}
  • dbt
  • semantic-layer
  • metricflow
  • metrics
  • dimensions
  • entities
  • yaml
  • dbt-core

README badge

README badge for dbt-labs/dbt-agent-skills/building-dbt-semantic-layer

Guides the creation and modification of dbt Semantic Layer components—semantic models, entities, dimensions, and metrics—across both legacy (dbt Core 1.6–1.11) and latest (dbt Core 1.12+) YAML specs. Covers metric types (simple, derived, cumulative, ratio, conversion), MetricFlow validation, and common configuration pitfalls.

Generated from the current SKILL.md.

What dbt Core versions does this skill support?
The skill covers both latest spec (dbt Core 1.12+ and Fusion) and legacy spec (dbt Core 1.6–1.11). Projects on Core 1.12+ can use either spec; older versions must use legacy spec.
Does this skill help migrate from legacy to latest semantic layer spec?
The skill mentions the migration path via `uvx dbt-autofix deprecations --semantic-layer` and references a migration guide, but does not automate the upgrade itself—it guides manual authoring in either spec.
What validation tools does this skill use?
The skill uses `dbt parse` (or `dbtf parse` for Fusion) for YAML syntax, and `dbt sl validate` or `mf validate-configs` (MetricFlow CLI) for semantic layer validation. Both must pass before work is complete.
Can I use raw table columns in metric filters?
No. Filter expressions can only reference columns declared as dimensions or entities in the semantic model. Raw columns that aren't defined as dimensions cannot be used in filters, even if they appear in a measure's expression.
Does this skill handle time-based metrics?
Yes. The skill covers cumulative, ratio, and conversion metric types that require time dimensions, and references a separate time spine setup guide for time-based aggregations.

Generated from the current SKILL.md. These answers refresh after source changes.