# dbt per Data Analyst nel 2026: Modellazione, Testing e Domande da Colloquio > Padroneggiare dbt (data build tool) per la data analytics — struttura del progetto, modellazione SQL, strategie di testing e domande frequenti nei colloqui con esempi pratici. - 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) si è affermato come lo strato di trasformazione standard nel moderno data stack. Le posizioni di data analyst nel 2026 richiedono sempre più competenze pratiche su dbt. Con [dbt Core v2.0 in fase alpha](https://github.com/dbt-labs/dbt-core) e la versione stabile v1.12, il framework copre ormai tutto — dalla modellazione SQL al testing automatizzato fino alla documentazione — il tutto versionato in Git. Questa guida affronta la struttura dei progetti dbt, i pattern di modellazione, le strategie di testing e le domande poste più frequentemente nei colloqui per posizioni di data analyst e [data engineering](/technologies/data-engineering). > **dbt nella pipeline ELT** > > dbt gestisce la T (Transform) in ELT. I dati grezzi arrivano nel warehouse tramite strumenti di ingestion (Fivetran, Airbyte), quindi dbt li trasforma in modelli puliti, testati e documentati, pronti per l'analisi. A differenza dell'ETL tradizionale, le trasformazioni vengono eseguite direttamente nel warehouse utilizzando SQL. ## Struttura del progetto dbt: Staging, Intermediate e Marts Un progetto dbt ben organizzato segue un'architettura a strati. Ogni strato ha una responsabilità specifica, e questa separazione previene query SQL disordinate che diventano impossibili da mantenere. La convenzione standard prevede tre strati: - **Staging** — modelli sottili che rinominano, convertono i tipi e puliscono i dati grezzi dalle sorgenti. Un modello staging per ogni tabella sorgente. - **Intermediate** — logica di business che unisce e aggrega i modelli staging. Sono blocchi costruttivi interni. - **Marts** — modelli finali consumati da dashboard, report e analisti. Ogni mart rappresenta un'entità di business o una metrica. ```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 ``` Il modello staging si occupa della conversione dei tipi e della rinomina delle colonne. Il modello mart contiene la logica di business. Questa separazione significa che una modifica nello schema sorgente richiede l'aggiornamento di un solo modello staging, non di ogni query a valle. ## Materializzazioni: Scegliere la strategia giusta dbt supporta quattro [materializzazioni](https://docs.getdbt.com/docs/build/materializations) principali che controllano come i modelli vengono persistiti nel warehouse. La scelta sbagliata porta a query lente oppure a costi di calcolo non necessari. | Materializzazione | Caso d'uso | Comportamento di rebuild | |-------------------|------------|-------------------------| | `view` | Modelli staging leggeri, bassa frequenza di query | Ricreata come SQL view ad ogni esecuzione | | `table` | Modelli mart interrogati spesso dalle dashboard | Ricostruzione completa della tabella ad ogni esecuzione | | `incremental` | Tabelle dei fatti grandi (eventi, log) | Aggiunge/merge solo le nuove righe | | `ephemeral` | CTE riutilizzabili, mai interrogate direttamente | Compilata inline come subquery | I modelli incrementali meritano attenzione speciale perché affrontano il collo di bottiglia più comune nelle performance — l'elaborazione di miliardi di righe ad ogni esecuzione. ```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 ``` La macro `is_incremental()` verifica se il modello esiste già. Alla prima esecuzione, dbt elabora tutti i dati. Nelle esecuzioni successive, vengono elaborate solo le nuove righe — riducendo un job di due ore a pochi minuti. ## Testare la qualità dei dati con dbt Il testing in dbt opera su due livelli: test dello schema definiti in YAML e test personalizzati scritti in SQL. Entrambi vengono eseguiti con `dbt test` e fanno fallire la pipeline se vengono trovate violazioni. I test dello schema coprono i controlli di qualità dei dati più comuni senza scrivere SQL: ```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 ``` Per logica di validazione complessa che YAML non riesce a esprimere, i test singolari personalizzati colmano la lacuna: ```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 ``` Qualsiasi riga restituita da un test singolare indica un fallimento. Questo pattern intercetta corruzione dei dati, bug upstream e errori logici prima che raggiungano le dashboard. ## Jinja e Macro: Logica SQL riutilizzabile dbt utilizza il [templating Jinja](https://docs.getdbt.com/docs/build/jinja-macros) per rendere il SQL dinamico. Le due funzioni più importanti sono `ref()` per i riferimenti ai modelli e `source()` per i riferimenti ai dati grezzi. Oltre a queste, le macro eliminano pattern SQL ripetitivi nell'intero progetto. ```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') }} ``` La macro viene compilata in SQL standard al momento della build. Questo approccio garantisce una logica di conversione valutaria consistente in ogni modello che gestisce valori monetari — una singola modifica nella macro si propaga ovunque. ## Domande da colloquio su dbt per Data Analyst Gli intervistatori che valutano la conoscenza di dbt si concentrano sulla comprensione pratica dello strumento piuttosto che su definizioni memorizzate. Le seguenti domande compaiono regolarmente nei colloqui per posizioni di [data analytics](/technologies/data-analytics). **D1: Qual è la differenza tra `ref()` e `source()`?** `source()` punta alle tabelle grezze caricate dagli strumenti di ingestion e definite in un file `sources.yml`. `ref()` punta ad altri modelli dbt. L'utilizzo di `ref()` costruisce il DAG (directed acyclic graph) che dbt usa per determinare l'ordine di esecuzione e tracciare la lineage dei dati. L'hardcoding dei nomi delle tabelle al posto di `ref()` interrompe il tracciamento della lineage e impedisce a dbt di eseguire i modelli nell'ordine corretto. **D2: Quando si dovrebbe usare un modello incrementale invece di una tabella?** I modelli incrementali sono appropriati quando i dati sorgente sono append-only o hanno una colonna timestamp affidabile, e la tabella è abbastanza grande da rendere le ricostruzioni complete troppo lente o costose. Tabelle di eventi, dati di log e serie temporali sono candidati tipici. Le tabelle dimensionali piccole dovrebbero rimanere come materializzazione `table` perché la complessità della logica incrementale non è giustificata. **D3: Come gestisce dbt le Slowly Changing Dimensions (SCD Tipo 2)?** Gli snapshot di dbt implementano il tracking SCD Tipo 2. Uno snapshot monitora una tabella sorgente e registra i cambiamenti nel tempo aggiungendo le colonne `dbt_valid_from` e `dbt_valid_to`. Esistono due strategie: `timestamp` (usa una colonna `updated_at`) e `check` (confronta direttamente i valori delle colonne). Gli snapshot vengono eseguiti con `dbt snapshot`, separatamente da `dbt run`. **D4: Spiegare il pattern staging/intermediate/marts.** I modelli staging puliscono e rinominano i dati grezzi delle sorgenti — un modello per tabella sorgente, nessun join, nessuna aggregazione. I modelli intermediate contengono la logica di business: join, filtri e calcoli che servono come blocchi costruttivi. I modelli mart sono gli output finali consumati da analisti e dashboard. Questa stratificazione assicura che ogni modello abbia una singola responsabilità e che i cambiamenti nello schema sorgente impattino solo i modelli staging. **D5: Come si differenziano i test personalizzati dai test dello schema?** I test dello schema sono dichiarati in YAML e coprono controlli standard: `unique`, `not_null`, `accepted_values` e `relationships`. I test singolari personalizzati sono query SQL archiviate nella directory `tests/` — qualsiasi riga restituita indica un fallimento. I test generici personalizzati sono macro parametrizzate riutilizzabili tra modelli come i test dello schema. I test dello schema si usano per vincoli comuni, i test singolari per regole di business complesse come "il fatturato non deve mai essere negativo." ## Best Practice dbt per progetti in produzione I progetti dbt in produzione che crescono oltre una manciata di modelli richiedono convenzioni consistenti. Queste pratiche prevengono il debito tecnico che si accumula quando più analisti contribuiscono allo stesso progetto. **Le convenzioni di nomenclatura** mantengono il progetto navigabile. I modelli staging usano il prefisso `stg_`, i modelli intermediate usano `int_`, e le tabelle dei fatti/dimensioni usano `fct_` o `dim_`. Le sottodirectory specifiche per sorgente (`models/staging/stripe/`, `models/staging/salesforce/`) raggruppano modelli correlati. **La documentazione vive accanto al codice.** Ogni modello e colonna dovrebbe avere una `description` nel file YAML corrispondente. L'esecuzione di `dbt docs generate` produce un sito di documentazione navigabile con un DAG visuale — essenziale per l'onboarding di nuovi membri del team e l'audit della lineage dei dati. **I controlli di freshness delle sorgenti** intercettano i fallimenti upstream prima che si propaghino: ```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 ``` L'esecuzione di `dbt source freshness` verifica se i dati sorgente sono stati aggiornati entro la finestra temporale prevista. Un gap di 24 ore nei dati di pagamento segnala un fallimento dell'ingestion che richiede investigazione prima di eseguire le trasformazioni. Per approfondire le competenze SQL applicate nei modelli dbt, le guide sulle [window function SQL e CTE](/blog/data-analytics/sql-window-functions-ctes-advanced-queries) e [SQL avanzato per i colloqui](/blog/data-analytics/advanced-sql-data-analyst-interviews) trattano i pattern di query utilizzati più frequentemente nei modelli staging e mart. ## Conclusione - dbt gestisce lo strato di trasformazione nelle pipeline ELT, eseguendo SQL direttamente nel data warehouse senza richiedere un motore di calcolo separato - Il pattern staging/intermediate/marts separa la pulizia delle sorgenti dalla logica di business, rendendo le modifiche prevedibili e isolate - Le materializzazioni incrementali riducono i tempi di elaborazione per tabelle grandi, gestendo solo le righe nuove o aggiornate - I test dello schema (YAML) coprono vincoli standard; i test singolari (SQL) validano regole di business complesse - Le macro Jinja eliminano logica SQL ripetuta e garantiscono consistenza tra i modelli - I controlli di freshness delle sorgenti intercettano fallimenti di ingestion upstream prima che corrompano i modelli a valle - La preparazione ai colloqui dovrebbe concentrarsi su scenari pratici — lineage del DAG, trade-off delle materializzazioni e strategie di testing — piuttosto che su definizioni memorizzate --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/it/blog/data-analytics/dbt-data-analysts-modeling-testing-interview-2026