# dbt voor Data Analysts in 2026: Modellering, Testing en Sollicitatievragen > dbt (data build tool) beheersen voor data-analyse — projectstructuur, SQL-modellering, teststrategieën en veelgestelde sollicitatievragen met praktische voorbeelden. - Published: 2026-06-17 - Updated: 2026-06-17 - Author: SharpSkill - Tags: dbt, data-analytics, sql, data-modeling, interview - Reading time: 9 min --- dbt (data build tool) heeft zich gevestigd als de standaard transformatielaag in de moderne data stack. Data-analystposities vereisen in 2026 steeds vaker praktische dbt-vaardigheden. Met [dbt Core v2.0 in alpha](https://github.com/dbt-labs/dbt-core) en de stabiele versie v1.12 dekt het framework inmiddels alles — van SQL-modellering tot geautomatiseerd testen en documentatie — volledig versiebeheerd in Git. Deze gids behandelt de dbt-projectstructuur, modelleringspatronen, teststrategieën en de sollicitatievragen die het vaakst gesteld worden in gesprekken voor data-analyst- en [data-engineering](/technologies/data-engineering)-posities. > **dbt in de ELT-pipeline** > > dbt verzorgt de T (Transform) in ELT. Ruwe data komt via ingestietools (Fivetran, Airbyte) in het warehouse terecht, waarna dbt deze transformeert tot schone, geteste en gedocumenteerde modellen die klaar zijn voor analyse. In tegenstelling tot traditionele ETL draaien de transformaties rechtstreeks in het warehouse met SQL. ## dbt-projectstructuur: Staging, Intermediate en Marts Een goed georganiseerd dbt-project volgt een gelaagde architectuur. Elke laag heeft een specifieke verantwoordelijkheid, en deze scheiding voorkomt onoverzichtelijke SQL die onmogelijk te onderhouden wordt. De standaardconventie gebruikt drie lagen: - **Staging** — dunne modellen die ruwe brondata hernoemen, type-converteren en opschonen. Per brontabel bestaat precies één stagingmodel. - **Intermediate** — bedrijfslogica die stagingmodellen koppelt en aggregeert. Dit zijn interne bouwstenen. - **Marts** — eindmodellen die geconsumeerd worden door dashboards, rapporten en analisten. Elke mart vertegenwoordigt een bedrijfsentiteit of metriek. ```sql -- models/staging/stripe/stg_stripe__payments.sql with source as ( select * from {{ source('stripe', 'payments') }} ), renamed as ( select id as payment_id, amount / 100.0 as amount_usd, -- Stripe stores cents status as payment_status, created::timestamp as created_at, customer_id from source where status != 'failed' -- Filter invalid records early ) select * from renamed ``` ```sql -- models/marts/finance/fct_monthly_revenue.sql with payments as ( select * from {{ ref('stg_stripe__payments') }} ), monthly as ( select date_trunc('month', created_at) as revenue_month, count(*) as total_transactions, sum(amount_usd) as gross_revenue, sum(case when payment_status = 'refunded' then amount_usd else 0 end) as refunds from payments group by 1 ) select revenue_month, total_transactions, gross_revenue, refunds, gross_revenue - refunds as net_revenue -- Key business metric from monthly ``` Het stagingmodel verzorgt typeconversies en hernoemingen. Het mart-model bevat de bedrijfslogica. Deze scheiding betekent dat een wijziging in het bronschema slechts de aanpassing van één enkel stagingmodel vereist — niet van elke downstream query. ## Materialisaties: De juiste strategie kiezen dbt ondersteunt vier kernmaterialisaties die bepalen hoe modellen in het warehouse worden opgeslagen. De verkeerde keuze leidt tot trage queries of onnodige rekenkosten. | Materialisatie | Toepassingsgebied | Rebuild-gedrag | |---------------|-------------------|----------------| | `view` | Lichte stagingmodellen, lage queryfrequentie | Wordt bij elke run als SQL view opnieuw aangemaakt | | `table` | Mart-modellen die vaak door dashboards worden bevraagd | Volledige tabelopbouw bij elke run | | `incremental` | Grote feitentabellen (events, logs) | Voegt alleen nieuwe rijen toe/mergt | | `ephemeral` | Herbruikbare CTE's, nooit direct bevraagd | Wordt inline als subquery gecompileerd | Incrementele modellen verdienen extra aandacht omdat ze het meest voorkomende performanceknelpunt aanpakken — het verwerken van miljarden rijen bij elke run. ```sql -- models/marts/product/fct_page_views.sql {{ config( materialized='incremental', unique_key='page_view_id', incremental_strategy='merge' ) }} with events as ( select event_id as page_view_id, user_id, page_url, session_id, event_timestamp from {{ ref('stg_snowplow__events') }} where event_type = 'page_view' {% if is_incremental() %} -- Only process new events since last run and event_timestamp > (select max(event_timestamp) from {{ this }}) {% endif %} ) select * from events ``` De macro `is_incremental()` controleert of het model al bestaat. Bij de eerste run verwerkt dbt alle data. Bij volgende runs worden alleen nieuwe rijen verwerkt — een job van twee uur wordt zo teruggebracht tot enkele minuten. ## Datakwaliteit testen met dbt Testen in dbt werkt op twee niveaus: schematests gedefinieerd in YAML en aangepaste tests geschreven in SQL. Beide worden uitgevoerd met `dbt test` en laten de pipeline falen wanneer overtredingen worden gevonden. Schematests dekken de meest voorkomende datakwaliteitscontroles zonder SQL te hoeven schrijven: ```yaml # models/staging/stripe/_stripe__models.yml version: 2 models: - name: stg_stripe__payments description: "Cleaned payment records from Stripe" columns: - name: payment_id description: "Unique payment identifier" tests: - unique - not_null - name: payment_status tests: - accepted_values: values: ['succeeded', 'pending', 'refunded'] - name: amount_usd tests: - not_null - dbt_utils.expression_is_true: expression: ">= 0" # No negative payments ``` Voor complexe validatielogica die YAML niet kan uitdrukken, vullen aangepaste singulaire tests het gat: ```sql -- tests/assert_revenue_not_negative.sql -- This test fails if any month has negative net revenue select revenue_month, net_revenue from {{ ref('fct_monthly_revenue') }} where net_revenue < 0 -- Should never happen ``` Elke rij die door een singulaire test wordt geretourneerd, duidt op een fout. Dit patroon detecteert datacorruptie, upstream-bugs en logicafouten voordat ze de dashboards bereiken. ## Jinja en Macro's: Herbruikbare SQL-logica dbt gebruikt [Jinja-templating](https://docs.getdbt.com/docs/build/jinja-macros) om SQL dynamisch te maken. De twee belangrijkste functies zijn `ref()` voor modelverwijzingen en `source()` voor verwijzingen naar ruwe data. Daarnaast elimineren macro's repetitieve SQL-patronen in het hele project. ```sql -- macros/cents_to_dollars.sql {% macro cents_to_dollars(column_name) %} ({{ column_name }} / 100.0)::numeric(12, 2) {% endmacro %} ``` ```sql -- Usage in any model select payment_id, {{ cents_to_dollars('amount_cents') }} as amount_usd, {{ cents_to_dollars('tax_cents') }} as tax_usd from {{ source('stripe', 'payments') }} ``` De macro wordt tijdens de build gecompileerd naar standaard SQL. Deze aanpak garandeert consistente valutaconversielogica in elk model dat met monetaire waarden werkt — een enkele wijziging in de macro werkt automatisch door overal. ## dbt-sollicitatievragen voor Data Analysts Interviewers die dbt-kennis toetsen, richten zich op praktisch begrip van het gereedschap in plaats van uit het hoofd geleerde definities. De volgende vragen komen regelmatig terug in gesprekken voor [data analytics](/technologies/data-analytics)-posities. **V1: Wat is het verschil tussen `ref()` en `source()`?** `source()` verwijst naar ruwe tabellen die door ingestietools worden geladen en gedefinieerd zijn in een `sources.yml`-bestand. `ref()` verwijst naar andere dbt-modellen. Het gebruik van `ref()` bouwt de DAG (directed acyclic graph) op die dbt gebruikt om de uitvoeringsvolgorde te bepalen en de data-lineage te volgen. Het hardcoden van tabelnamen in plaats van `ref()` doorbreekt de lineage-tracking en voorkomt dat dbt modellen in de juiste volgorde uitvoert. **V2: Wanneer moet een incrementeel model worden gebruikt in plaats van een tabel?** Incrementele modellen zijn geschikt wanneer de brondata append-only is of een betrouwbare tijdstempelkolom heeft, en de tabel groot genoeg is dat volledige herbouwen te langzaam of te duur is. Eventtabellen, logdata en tijdreeksdata zijn typische kandidaten. Kleine dimensietabellen behoren als `table`-materialisatie te blijven omdat de complexiteit van incrementele logica niet gerechtvaardigd is. **V3: Hoe gaat dbt om met Slowly Changing Dimensions (SCD Type 2)?** dbt-snapshots implementeren SCD Type 2-tracking. Een snapshot bewaakt een brontabel en registreert wijzigingen door de kolommen `dbt_valid_from` en `dbt_valid_to` toe te voegen. Er bestaan twee strategieën: `timestamp` (gebruikt een `updated_at`-kolom) en `check` (vergelijkt kolomwaarden direct). Snapshots worden uitgevoerd met `dbt snapshot`, apart van `dbt run`. **V4: Het staging/intermediate/marts-patroon uitleggen.** Stagingmodellen schonen ruwe brondata op en hernoemen deze — één model per brontabel, geen joins, geen aggregaties. Intermediate-modellen bevatten de bedrijfslogica: joins, filters en berekeningen die als bouwstenen dienen. Mart-modellen zijn de eindresultaten die door analisten en dashboards worden geconsumeerd. Deze gelaagdheid zorgt ervoor dat elk model een enkele verantwoordelijkheid heeft en dat wijzigingen in het bronschema alleen stagingmodellen raken. **V5: Hoe verschillen aangepaste tests van schematests?** Schematests worden gedeclareerd in YAML en dekken standaardcontroles: `unique`, `not_null`, `accepted_values` en `relationships`. Aangepaste singulaire tests zijn SQL-queries in de `tests/`-directory — elke geretourneerde rij duidt op een fout. Aangepaste generieke tests zijn geparametriseerde macro's die hergebruikt kunnen worden over modellen heen, net als schematests. Schematests worden gebruikt voor gangbare constraints, singulaire tests voor complexe bedrijfsregels zoals "de omzet mag nooit negatief zijn." ## dbt Best Practices voor productieprojecten dbt-projecten in productie die uitgroeien voorbij een handvol modellen vereisen consistente conventies. Deze praktijken voorkomen de technische schuld die zich ophoopt wanneer meerdere analisten aan hetzelfde project bijdragen. **Naamconventies** houden het project navigeerbaar. Stagingmodellen gebruiken het prefix `stg_`, intermediate-modellen `int_`, en feiten-/dimensietabellen `fct_` of `dim_`. Bronspecifieke subdirectories (`models/staging/stripe/`, `models/staging/salesforce/`) groeperen gerelateerde modellen. **Documentatie leeft naast de code.** Elk model en elke kolom dient een `description` te hebben in het bijbehorende YAML-bestand. Het uitvoeren van `dbt docs generate` produceert een doorzoekbare documentatiewebsite met een visuele DAG — onmisbaar voor het inwerken van nieuwe teamleden en het auditen van de data-lineage. **Source-freshness-checks** detecteren upstream-fouten voordat ze zich verspreiden: ```yaml # models/staging/stripe/_stripe__sources.yml version: 2 sources: - name: stripe database: raw schema: stripe freshness: warn_after: {count: 12, period: hour} error_after: {count: 24, period: hour} loaded_at_field: _fivetran_synced tables: - name: payments - name: customers ``` Het commando `dbt source freshness` controleert of de brondata binnen het verwachte tijdsvenster is bijgewerkt. Een gat van 24 uur in betalingsdata signaleert een ingestiefout die onderzocht moet worden voordat transformaties worden uitgevoerd. Voor verdiepende SQL-vaardigheden die in dbt-modellen worden toegepast, behandelen de gidsen over [SQL window functions en CTE's](/blog/data-analytics/sql-window-functions-ctes-advanced-queries) en [geavanceerd SQL voor sollicitatiegesprekken](/blog/data-analytics/advanced-sql-data-analyst-interviews) de querypatronen die het vaakst voorkomen in staging- en mart-modellen. ## Conclusie - dbt verzorgt de transformatielaag in ELT-pipelines en voert SQL rechtstreeks uit in het datawarehouse zonder een aparte compute-engine te vereisen - Het staging/intermediate/marts-patroon scheidt bronopschoning van bedrijfslogica, waardoor wijzigingen voorspelbaar en geïsoleerd zijn - Incrementele materialisaties verminderen de verwerkingstijd voor grote tabellen door alleen nieuwe of bijgewerkte rijen te verwerken - Schematests (YAML) dekken standaardconstraints; singulaire tests (SQL) valideren complexe bedrijfsregels - Jinja-macro's elimineren herhaalde SQL-logica en waarborgen consistentie over alle modellen - Source-freshness-checks detecteren upstream-ingestiefouten voordat ze downstream-modellen beschadigen - De sollicitatievoorbereiding dient zich te richten op praktische scenario's — DAG-lineage, materialisatie-afwegingen en teststrategieën — in plaats van uit het hoofd geleerde definities --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/nl/blog/data-analytics/dbt-data-analysts-modeling-testing-interview-2026