In Power BI, capire come DAX “vede” i dati in un dato momento è la chiave per scrivere colonne calcolate e misure corrette. Due meccanismi governano questa visione: il row context (contesto di riga) e il filter context (contesto di filtro). Sono concetti distinti, spesso confusi, e distinguerli è ciò che separa una formula che funziona per caso da una progettata con criterio.

Row context: una riga alla volta

Il row context è l’idea che DAX stia elaborando una singola riga di una tabella. Quando esiste un row context, ha senso riferirsi a una colonna “nuda” come Vendite[Quantità]: DAX sa a quale riga appartiene quel valore.

Il row context nasce automaticamente in due casi:

  • Nelle colonne calcolate: DAX percorre la tabella riga per riga e valuta l’espressione nel contesto di ciascuna.
  • Nelle funzioni iteratrici (le funzioni con la “X” finale: SUMX, AVERAGEX, MAXX, RANKX, FILTER…), che scorrono la tabella indicata e valutano l’espressione per ogni riga, poi aggregano.
Margine Totale = SUMX ( Vendite, Vendite[Prezzo] * Vendite[Quantità] )

Qui SUMX crea un row context su Vendite: per ogni riga calcola Prezzo * Quantità, e solo alla fine somma. Punto cruciale: il row context NON filtra il modello e non attraversa da solo le relazioni. Una colonna calcolata in Vendite non “vede” automaticamente i valori aggregati di altre tabelle: per raggiungere il lato uno serve RELATED, per aggregare il lato molti serve un’iteratrice esplicita.

Filter context: l’insieme dei filtri attivi

Il filter context è l’insieme di tutti i filtri applicati al modello quando una misura viene valutata. Contribuiscono al filter context:

  • gli assi del visual (righe/colonne di una matrice, categorie di un grafico);
  • gli slicer e i filtri (a livello di visual, pagina, report);
  • le interazioni cross-filter tra visual;
  • eventuali filtri imposti da CALCULATE.

Ogni cella di una matrice ha un proprio filter context. Una misura come Totale Vendite = SUM ( Vendite[Importo] ) restituisce numeri diversi in ogni cella perché il filter context cambia: anno = 2026, categoria = “Laptop”, regione = “Nord”, e così via. Le misure rispondono al filter context; le colonne calcolate no, perché sono materializzate al refresh del modello, quando il contesto del report non esiste ancora.

La propagazione lungo le relazioni

Il filter context non resta confinato alla tabella filtrata: si propaga lungo le relazioni. In un modello a stella con relazioni a cardinalità uno-a-molti e direzione filtro single (default e best practice), il filtro fluisce dal lato uno (le dimensioni: Date, Prodotto, Cliente) verso il lato molti (la fact table Vendite).

Quindi selezionare Prodotto[Categoria] = "Laptop" in uno slicer filtra la dimensione Prodotto, e attraverso la relazione questo filtro scende su Vendite, riducendo le righe che la misura aggrega. Al contrario, un filtro sulla fact table non risale da solo alla dimensione, salvo attivare il cross-filter bidirezionale (da usare con parsimonia: costa in performance e può introdurre ambiguità). Ricordare la direzione uno → molti è la base per prevedere il numero che una misura produrrà.

Il ponte: context transition

Cosa succede quando serve combinare i due mondi, ad esempio calcolare un totale che tenga conto della riga corrente di un’iterazione? Qui entra in gioco la context transition: il meccanismo per cui CALCULATE trasforma il row context corrente in un equivalente filter context. In pratica, i valori della riga su cui stiamo iterando diventano filtri che si propagano nel modello lungo le relazioni.

È il motivo per cui una misura richiamata dentro un’iteratrice “funziona” riga per riga: il richiamo di una misura ha un CALCULATE implicito, che scatena la context transition. Non svilupperemo qui la sintassi: è il cuore dell’unità successiva su CALCULATE, il modificatore di contesto più importante di DAX. Per ora è sufficiente fissare l’idea: row context e filter context sono ponti che CALCULATE collega.

Trappole tipiche d’esame

  • Scenario: una colonna calcolata in Vendite deve mostrare il totale di categoria e restituisce sempre il valore di riga. → Le colonne calcolate hanno solo row context: serve un’iteratrice o CALCULATE per creare un filter context, non una colonna nuda.
  • Scenario: uno slicer sulla fact table dovrebbe filtrare una dimensione ma non ha effetto. → Il filtro si propaga uno → molti, non molti → uno; valutare il cross-filter bidirezionale solo se davvero necessario.
  • Scenario: la stessa misura dà risultati diversi in ogni cella di una matrice. → Comportamento corretto: ogni cella ha il proprio filter context dato dagli assi.
  • Scenario: serve sommare Prezzo × Quantità riga per riga. → Usare SUMX (iteratrice con row context), non SUM su una moltiplicazione di colonne aggregate.
  • Scenario: una misura richiamata dentro SUMX sembra “conoscere” la riga corrente. → È la context transition innescata dal CALCULATE implicito della misura.