Blueprints Blog Contact About

SCD2 Dimension

Track dimension history with Slowly Changing Dimension Type 2

This example shows how to track the complete history of a dimension table using SCD2.

1. Source Data

-- models/raw/customers.sql
-- @kind: table

SELECT * FROM (VALUES
    (1, 'Alice', 'alice@example.com', 'gold',   'Sweden',  '2026-03-28 10:00:00'),
    (2, 'Bob',   'bob@example.com',   'silver', 'Norway',  '2026-03-28 10:00:00'),
    (3, 'Carol', 'carol@example.com', 'bronze', 'Denmark', '2026-03-29 12:00:00')
) AS t(customer_id, name, email, tier, country, updated_at)

2. SCD2 Model

-- models/staging/stg_customers.sql
-- @kind: scd2
-- @unique_key: customer_id
-- @constraint: customer_id NOT NULL
-- @audit: row_count > 0

SELECT
    customer_id,
    name,
    email,
    tier,
    country,
    updated_at
FROM raw.customers

3. First Run

ondatrasql run
Running 2 models...
[OK] raw.customers (table, backfill, 3 rows, 174ms — first run)
[OK] staging.stg_customers (scd2, backfill, 3 rows, 269ms — first run)

All rows are inserted with is_current = true:

customer_idnametieris_current
1Alicegoldtrue
2Bobsilvertrue
3Carolbronzetrue

4. When Data Changes

Change Alice’s tier from “gold” to “platinum” in raw/customers.sql, then run again:

ondatrasql run
Running 2 models...
[OK] raw.customers (table, backfill, 3 rows, 158ms — sql changed)
[OK] staging.stg_customers (scd2, incremental, 1 rows, 360ms — unchanged)

The old version is closed and a new version is inserted:

customer_idnametieris_current
1Alicegoldfalse
1Aliceplatinumtrue
2Bobsilvertrue
3Carolbronzetrue

Auto-Generated Columns

OndatraSQL automatically adds three columns to the output:

ColumnTypeDescription
valid_from_snapshotBIGINTDuckLake snapshot ID when this version became active
valid_to_snapshotBIGINTSnapshot ID when superseded (NULL if current)
is_currentBOOLEANWhether this is the active version

Querying SCD2 Data

-- Current state
SELECT * FROM staging.stg_customers WHERE is_current = true;

-- Full history for a customer
SELECT * FROM staging.stg_customers
WHERE customer_id = 1
ORDER BY valid_from_snapshot;