Slowly Changing Dimensions: De 7 SCD Typen Uitgelegd

Gepubliceerd: 19 april 2026
Leestijd: 14 minuten
Data Warehousing, Dimensioneel Modelleren

Hoe ga je om met veranderende data in je dimensietabellen? Ontdek alle 7 SCD-typen (Type 0 t/m 6) met praktische voorbeelden, SQL-code en een duidelijk beslisschema.

Wat zijn Slowly Changing Dimensions?

In elk data warehouse veranderen dimensiegegevens over tijd. Een klant verhuist, een medewerker krijgt een nieuwe functietitel, een product wisselt van categorie. De vraag is: hoe sla je die veranderingen op? Overschrijf je de oude waarde? Bewaar je de historie? Of doe je iets daartussenin?

Slowly Changing Dimensions (SCD) is het raamwerk uit de dimensionele modellering (Kimball-methode) dat precies dit probleem oplost. Er zijn 7 typen (Type 0 t/m Type 6), elk met een eigen strategie voor het omgaan met veranderingen in dimensietabellen.

SCD in het kort

Slowly Changing Dimensions zijn technieken om veranderingen in dimensiedata (klanten, producten, medewerkers) te verwerken in een data warehouse, variërend van het negeren van wijzigingen (Type 0) tot een complete hybride aanpak met volledige historie en actuele waarde (Type 6).

Overzicht van de 7 SCD typen: Type 0 t/m Type 6 met kenmerken en voorbeelden

SCD Type 0 — Retain Original (Niet Wijzigen)

Bij Type 0 worden attributen nooit bijgewerkt na de initiële opslag. De waarde op het moment van eerste invoer blijft voor altijd staan, ongeacht latere wijzigingen in het bronsysteem.

Wanneer gebruiken?

  • Attributen die per definitie niet mogen veranderen (geboortedatum, BSN, originele registratiedatum)
  • Wettelijke of audit-vereisten waarbij de oorspronkelijke waarde bewaard moet blijven
  • Referentiedata die als vaststaand wordt beschouwd
-- Type 0: Geen update op originele waarden
-- De kolom geboortedatum wordt nooit geüpdatet
INSERT INTO dim_klant (klant_id, naam, geboortedatum, registratiedatum)
SELECT klant_id, naam, geboortedatum, CURRENT_DATE
FROM staging_klant s
WHERE NOT EXISTS (
    SELECT 1 FROM dim_klant d WHERE d.klant_id = s.klant_id
);

Tip

Type 0 wordt vaak gecombineerd met andere SCD-typen. Binnen dezelfde dimensietabel kan de ene kolom Type 0 zijn (geboortedatum) en een andere kolom Type 2 (adres).

SCD Type 1 — Overschrijven

Type 1 is de eenvoudigste aanpak: bij een wijziging wordt de oude waarde overschreven met de nieuwe. Er is geen historie beschikbaar — je hebt altijd alleen de meest actuele waarde.

Wanneer gebruiken?

  • Correcties van fouten (typfout in een naam)
  • Attributen waarvan de historie niet relevant is voor rapportages
  • Eenvoud boven volledigheid — kleine dimensies zonder auditverplichtingen
-- Type 1: Overschrijf de oude waarde
UPDATE dim_klant
SET
    email = s.email,
    telefoonnummer = s.telefoonnummer
FROM staging_klant s
WHERE dim_klant.klant_id = s.klant_id
  AND (dim_klant.email != s.email
       OR dim_klant.telefoonnummer != s.telefoonnummer);
Voordelen Nadelen
Eenvoudig te implementeren Geen historie beschikbaar
Geen tabelgroei Historische rapportages geven verkeerde resultaten
Altijd actuele waarde Onmogelijk om trends in dimensiedata te analyseren

SCD Type 2 — Historische Rijen

Type 2 is het meest gebruikte SCD-type in de praktijk. Bij elke wijziging wordt een nieuwe rij aangemaakt met de nieuwe waarden, terwijl de oude rij actief blijft met een einddatum. Zo heb je volledige historie van elke verandering.

Hoe werkt het?

Elke rij krijgt extra kolommen om de geldigheid bij te houden:

  • surrogate_key — unieke sleutel per versie
  • geldig_van — startdatum van deze versie
  • geldig_tot — einddatum (NULL of 9999-12-31 voor de huidige versie)
  • is_actueel — boolean flag voor de actieve rij
-- Type 2: Sluit de oude rij af
UPDATE dim_klant
SET geldig_tot = CURRENT_DATE - INTERVAL '1 day',
    is_actueel = FALSE
WHERE klant_id = 1001
  AND is_actueel = TRUE;

-- Voeg de nieuwe versie in
INSERT INTO dim_klant (klant_sk, klant_id, naam, stad, geldig_van, geldig_tot, is_actueel)
VALUES (nextval('dim_klant_seq'), 1001, 'Jan de Vries', 'Rotterdam',
        CURRENT_DATE, '9999-12-31', TRUE);

Voorbeeld: klant verhuist

klant_skklant_idnaamstadgeldig_vangeldig_totis_actueel
1011001Jan de VriesAmsterdam2024-01-152026-04-18FALSE
1021001Jan de VriesRotterdam2026-04-199999-12-31TRUE

Type 2 is de standaardkeuze wanneer je historische rapportages nodig hebt. Het nadeel is tabelgroei — bij veel wijzigingen groeit de dimensietabel snel. Lees ook onze SCD Type 2 implementatie in Databricks voor een praktische handleiding.

SCD Type 3 — Vorige en Huidige Waarde

Type 3 bewaart beperkte historie door een extra kolom toe te voegen voor de vorige waarde. Er wordt geen nieuwe rij aangemaakt — de tabel heeft een vaste breedte.

-- Type 3: Tabelstructuur met vorige waarde
ALTER TABLE dim_klant ADD COLUMN vorige_stad VARCHAR(100);
ALTER TABLE dim_klant ADD COLUMN stad_gewijzigd_op DATE;

-- Bij een verhuizing:
UPDATE dim_klant
SET vorige_stad = stad,
    stad = 'Rotterdam',
    stad_gewijzigd_op = CURRENT_DATE
WHERE klant_id = 1001;

Wanneer gebruiken?

  • Je hebt alleen de vorige en huidige waarde nodig (niet de volledige historie)
  • Vergelijking "voor en na" (bijv. reorganisatie: oude afdeling vs. nieuwe afdeling)
  • Wanneer tabelgroei absoluut vermeden moet worden
Voordelen Nadelen
Geen tabelgroei (vaste rijcount) Slechts 1 vorige waarde beschikbaar
Eenvoudige queries (geen joins op datums) Niet schaalbaar naar meerdere historische wijzigingen
Geschikt voor eenvoudige voor/na-analyses Extra kolommen per getrackt attribuut

SCD Type 4 — Aparte Historietabel

Type 4 houdt de hoofddimensietabel compact (altijd alleen de actuele waarde) en verplaatst alle historie naar een aparte tabel. Dit geeft het beste van twee werelden: snelle lookups op de actuele data en volledige historie als dat nodig is.

-- Type 4: Hoofdtabel bevat alleen de actuele waarde
CREATE TABLE dim_klant (
    klant_id    INT PRIMARY KEY,
    naam        VARCHAR(100),
    stad        VARCHAR(100),
    email       VARCHAR(200)
);

-- Historietabel voor alle wijzigingen
CREATE TABLE dim_klant_historie (
    historie_id SERIAL PRIMARY KEY,
    klant_id    INT,
    naam        VARCHAR(100),
    stad        VARCHAR(100),
    email       VARCHAR(200),
    geldig_van  DATE,
    geldig_tot  DATE
);

-- Bij wijziging: archiveer de oude waarde
INSERT INTO dim_klant_historie (klant_id, naam, stad, email, geldig_van, geldig_tot)
SELECT klant_id, naam, stad, email, geldig_van, CURRENT_DATE - INTERVAL '1 day'
FROM dim_klant WHERE klant_id = 1001;

-- Update de hoofdtabel
UPDATE dim_klant
SET stad = 'Rotterdam', geldig_van = CURRENT_DATE
WHERE klant_id = 1001;

Wanneer gebruiken?

  • Performance-kritieke dimensietabellen waar de hoofdtabel compact moet blijven
  • Grote dimensies met veel wijzigingen (bijv. miljoenen klanten die regelmatig verhuizen)
  • Rapportages die vooral actuele data nodig hebben, met incidentele historische analyses

SCD Type 5 — Type 4 + Type 1 Mini-Dimensie

Type 5 combineert een mini-dimensie (Type 4) met een outrigger op de hoofddimensie. De mini-dimensie bevat snel-veranderende attributen, en de hoofddimensie heeft een foreign key naar de huidige mini-dimensie rij (Type 1 overschrijving).

-- Type 5: Mini-dimensie voor snel-veranderende attributen
CREATE TABLE dim_klant_profiel (
    profiel_sk       SERIAL PRIMARY KEY,
    leeftijdsgroep   VARCHAR(20),
    inkomensklasse   VARCHAR(20),
    segment          VARCHAR(50)
);

-- Hoofddimensie met outrigger naar actueel profiel
CREATE TABLE dim_klant (
    klant_sk            SERIAL PRIMARY KEY,
    klant_id            INT,
    naam                VARCHAR(100),
    huidig_profiel_sk   INT REFERENCES dim_klant_profiel(profiel_sk)  -- Type 1: altijd actueel
);

-- Feitentabel verwijst naar het profiel op moment van transactie
CREATE TABLE feit_orders (
    order_id        INT,
    klant_sk        INT REFERENCES dim_klant(klant_sk),
    profiel_sk      INT REFERENCES dim_klant_profiel(profiel_sk),  -- Profiel op dat moment
    order_datum     DATE,
    bedrag          DECIMAL(10,2)
);

Wanneer gebruiken?

  • Dimensies met een mix van stabiele en snel-veranderende attributen
  • Demografische data (leeftijdsgroep, inkomenssegment) die regelmatig verschuift
  • Je wilt de feitentabel koppelen aan zowel het huidige als het historische profiel

SCD Type 6 — Hybride (1 + 2 + 3)

Type 6 is de meest complete aanpak en combineert Type 1, Type 2 en Type 3 in één tabel. Elke rij bevat de huidige waarde (Type 1), de historische waarde voor die versie (Type 2), en een kolom met de actuele waarde die in alle rijen wordt bijgewerkt (Type 3-achtig).

-- Type 6: Hybride aanpak (ook wel "Type 2+1+3" of "Hybrid SCD")
CREATE TABLE dim_klant (
    klant_sk       SERIAL PRIMARY KEY,
    klant_id       INT,
    naam           VARCHAR(100),
    stad           VARCHAR(100),           -- Historische waarde (Type 2)
    huidige_stad   VARCHAR(100),           -- Altijd actueel (Type 1 overwrite)
    geldig_van     DATE,
    geldig_tot     DATE,
    is_actueel     BOOLEAN
);

-- Bij verhuizing van Amsterdam naar Rotterdam:

-- Stap 1: Sluit de oude rij (Type 2)
UPDATE dim_klant
SET geldig_tot = CURRENT_DATE - INTERVAL '1 day',
    is_actueel = FALSE,
    huidige_stad = 'Rotterdam'    -- Type 1: update in ALLE rijen
WHERE klant_id = 1001 AND is_actueel = TRUE;

-- Stap 2: Nieuwe rij (Type 2)
INSERT INTO dim_klant (klant_id, naam, stad, huidige_stad, geldig_van, geldig_tot, is_actueel)
VALUES (1001, 'Jan de Vries', 'Rotterdam', 'Rotterdam', CURRENT_DATE, '9999-12-31', TRUE);

-- Stap 3: Update huidige_stad in ALLE historische rijen (Type 1 overwrite)
UPDATE dim_klant
SET huidige_stad = 'Rotterdam'
WHERE klant_id = 1001;

Resultaat na verhuizing

klant_skklant_idstadhuidige_stadgeldig_vangeldig_totis_actueel
1011001AmsterdamRotterdam2024-01-152026-04-18FALSE
1021001RotterdamRotterdam2026-04-199999-12-31TRUE

De kolom stad geeft de waarde op dat moment, huidige_stad geeft altijd de laatste waarde — ideaal voor rapportages die beide perspectieven nodig hebben.

Wanneer gebruiken?

  • Maximale flexibiliteit: je wilt zowel historische als actuele waarden in elke query
  • Complexe rapportages die "wie was de klant toen?" en "wie is de klant nu?" combineren
  • Business cases met zware audit- en compliancevereisten

Vergelijking: Welk SCD Type Kies Je?

Onderstaande tabel helpt je bij het kiezen van het juiste SCD-type voor jouw situatie.

Kenmerk Type 0 Type 1 Type 2 Type 3 Type 4 Type 5 Type 6
Historie bewaard? Nee Nee Volledig 1 vorige Volledig Volledig Volledig
Tabelgroei Geen Geen Hoog Geen Laag (apart) Laag (apart) Hoog
Complexiteit Laag Laag Middel Laag Middel Hoog Hoog
Actuele waarde? Origineel Ja Via filter Ja Ja Ja Ja (kolom)
Gebruiksfrequentie Laag Hoog Zeer hoog Laag Middel Laag Middel

Beslisboom: Het Juiste SCD Type in 3 Vragen

Gebruik dit eenvoudige beslisschema om snel het juiste type te bepalen:

Vraag 1: Heb je historie nodig?

Nee → Type 0 (nooit wijzigen) of Type 1 (overschrijven).
Ja → Ga naar vraag 2.

Vraag 2: Hoeveel historie?

Alleen vorige waarde → Type 3.
Volledige historie → Ga naar vraag 3.

Vraag 3: Eén tabel of gescheiden?

Eén tabel, eenvoudig → Type 2.
Eén tabel, met actuele waarde erbij → Type 6.
Gescheiden tabellen → Type 4 of Type 5.

SCD in Moderne Data Platforms

In de praktijk worden SCD-patronen ondersteund door alle grote data platforms. Hier een overzicht van hoe je SCD implementeert in populaire tools:

Databricks / Delta Lake

Delta Lake's MERGE INTO maakt SCD Type 2 implementatie elegant en performant. Lees onze uitgebreide handleiding SCD Type 2 in Databricks.

MERGE INTO dim_klant AS target
USING staging_klant AS source
ON target.klant_id = source.klant_id AND target.is_actueel = TRUE
WHEN MATCHED AND target.stad != source.stad THEN
  UPDATE SET geldig_tot = current_date(), is_actueel = FALSE
WHEN NOT MATCHED THEN
  INSERT (klant_id, naam, stad, geldig_van, geldig_tot, is_actueel)
  VALUES (source.klant_id, source.naam, source.stad, current_date(), '9999-12-31', TRUE);

dbt (Data Build Tool)

dbt heeft native SCD Type 2 support via snapshots. Je definieert een snapshot-strategie en dbt handelt de rest af:

-- dbt snapshot (models/snapshots/snap_klant.sql)
{% snapshot snap_klant %}
{{
    config(
      target_schema='snapshots',
      unique_key='klant_id',
      strategy='check',
      check_cols=['naam', 'stad', 'email']
    )
}}
SELECT * FROM {{ source('crm', 'klanten') }}
{% endsnapshot %}

Microsoft Fabric / Synapse

In Fabric kun je SCD implementeren via Dataflows Gen2 (visueel) of via Spark notebooks met Delta Lake — dezelfde MERGE-syntax als Databricks.

Veelgemaakte Fouten bij SCD

Na honderden SCD-implementaties te hebben gezien, zijn dit de meest voorkomende valkuilen:

Alles Type 2 maken

Niet elk attribuut heeft volledige historie nodig. Gebruik Type 1 voor correcties en Type 0 voor onveranderlijke velden. Combineer typen binnen dezelfde tabel.

Geen surrogate key

Bij Type 2 heb je een surrogate key nodig (klant_sk) naast de business key (klant_id). Zonder surrogate key werken joins met de feitentabel niet correct.

Datum-gaten in historie

Zorg dat geldig_tot van de oude rij aansluit op geldig_van van de nieuwe. Eén dag overlap of gap verstoort point-in-time queries volledig.

Conclusie

Slowly Changing Dimensions zijn een fundamenteel onderdeel van elk data warehouse. De keuze tussen de 7 typen hangt af van je business requirements: heb je historie nodig? Hoeveel? En hoe complex mag de implementatie zijn?

In de praktijk werken de meeste data warehouses met een combinatie van SCD-typen:

  • Type 0 voor onveranderlijke attributen (geboortedatum, BSN)
  • Type 1 voor correcties en niet-historische attributen
  • Type 2 voor attributen met auditverplichtingen of rapportage-historie
  • Type 6 voor complexe dimensies die zowel historische als actuele analyse vereisen

Begin altijd met het stellen van de juiste vraag: "Heeft de business behoefte aan historische analyse van dit attribuut?" Het antwoord bepaalt welk SCD-type de juiste keuze is.

Hulp Nodig bij Implementatie?

Zoek je een Data Engineer of advies over dit onderwerp?