Add a New Mart Model
This skill adds a new mart model to the dbt project, following the established conventions for facts, dimensions, and reporting views.
When to Use
- Creating a new analytics table for BI tools or downstream consumers
- Building a fact table from staging or intermediate models
- Creating a dimension table for reference data
- Publishing a model to the REPORTING schema for BI tool access
Before You Start
Gather the following information:
- Model type - fact (
fct_), dimension (dim_), or reporting (rpt_) - Domain - business area:
core,crm,finance, etc. - Source models - which staging or intermediate models it references (use
ref()) - Materialisation -
table(small, static) orincremental(large, growing) - For incremental -
unique_keyand incremental strategy (mergeordelete+insert) - Whether to publish to REPORTING - should BI users see this model?
Reference: Existing Marts
Read models/marts/ to see existing patterns:
models/marts/
├── core/
│ ├── fct_exchange_rates.sql / .yml # Incremental fact table
│ ├── dim_currencies.sql / .yml # Table dimension
│ └── dim_products.sql / .yml # Table dimension
├── crm/
│ ├── fct_contacts.sql / .yml # Table fact
└── reporting/
├── rpt_contacts.sql / .yml # View over fct_contacts
Steps
1. Create Model SQL
Create models/marts/{domain}/{model_name}.sql.
For table materialisation (small or static datasets):
{{ config(
materialized='table'
) }}
with {source_cte} as (
select * from {{ ref('{upstream_model}') }}
),
final as (
select
{columns}
from {source_cte}
)
select * from final
For incremental materialisation (large or growing fact tables):
{{ config(
materialized='incremental',
unique_key='{unique_key}',
on_schema_change='append_new_columns'
) }}
with source as (
select * from {{ ref('{upstream_model}') }}
{% if is_incremental() %}
where {timestamp_column} > (select max({timestamp_column}) from {{ this }})
{% endif %}
),
final as (
select
{columns}
from source
)
select * from final
2. Create Model YAML
Create models/marts/{domain}/{model_name}.yml:
version: 2
models:
- name: {model_name}
description: >
Description of the model and its business purpose.
Explain what each row represents and the grain of the table.
columns:
- name: {primary_key}
description: Primary key (surrogate or natural).
data_tests:
- unique
- not_null
- name: {foreign_key}
description: Foreign key to {referenced_model}.
data_tests:
- relationships:
to: ref('{referenced_model}')
field: {referenced_column}
- name: {other_columns}
description: Column description.
3. Create Reporting View (if Publishing to BI)
If the model should be visible to BI tools and the ANALYTICS_REPORTER role, create a reporting view.
Create models/marts/reporting/rpt_{entity}.sql:
/*
Reporting view over {source_mart_model}.
Published to ANALYTICS.REPORTING for BI tool access.
*/
select * from {{ ref('{mart_model}') }}
Create models/marts/reporting/rpt_{entity}.yml:
version: 2
models:
- name: rpt_{entity}
description: >
Reporting view over {mart_model}. Published to the REPORTING schema
for BI tool access via the ANALYTICS_REPORTER role.
columns:
- name: {primary_key}
description: Primary key.
data_tests:
- unique
- not_null
4. Validate
dbt run -s {model_name}
dbt test -s {model_name}
For incremental models, also verify the incremental logic:
# Full refresh to build the complete table
dbt run -s {model_name} --full-refresh
# Run again to test incremental behaviour
dbt run -s {model_name}
Schema Mapping
| Directory | Schema | Access Role |
|---|---|---|
models/marts/core/ |
ANALYTICS.MARTS |
ANALYTICS_DEVELOPER |
models/marts/crm/ |
ANALYTICS.MARTS |
ANALYTICS_DEVELOPER |
models/marts/{domain}/ |
ANALYTICS.MARTS |
ANALYTICS_DEVELOPER |
models/marts/reporting/ |
ANALYTICS.REPORTING |
ANALYTICS_REPORTER |
The schema routing is configured in dbt_project.yml - you do not need to set schemas in model configs.
Naming Rules
| Model Type | Prefix | Description | Example |
|---|---|---|---|
| Fact table | fct_ |
Events, transactions, measurable actions | fct_exchange_rates |
| Dimension table | dim_ |
Descriptive, reference, slowly changing | dim_currencies |
| Reporting view | rpt_ |
Curated subset for BI tools | rpt_contacts |
Testing Requirements
- Primary key:
unique+not_null - Foreign keys:
relationshipstest to the referenced dimension - All columns: description in YAML file
- Incremental models: verify both full-refresh and incremental runs work correctly