Formule Dax - Filter Context / Row Context - Problema con esempio L’argomento è risolto

Il software per la BI di Microsoft, leader nel mercato
Rispondi
Avatar utente

Mohican1989
Messaggi: 8 | Topic creati
Iscritto il: ven 10 lug 2020, 16:40
Ringraziato: 1 volta
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Mohican1989 »

Buonasera, allego un file con contenuto d' esempio (https://gofile.io/d/XGFvP6).
Riporto il mio problema sperando che sia di aiuto anche a chi come me sta avendo un po' di difficoltà ad apprendere i vari comportamenti delle formule dax rispetto ai contesti in cui vengono utilizzate. Io personalmente, per "capire" ho bisogno di immaginare i vari step che influenzano i risultati delle mie formule.
Perdonate il post molto lungo, ma un altro modo per imparare è provare a spiegare come si ottengono dei risultati e quindi annoterò anche i passaggi eseguiti prima di esporre il dubbio.

Nel file di esempio abbiamo relazionate 3 tabelle:
Sales -> in cui sono contenuti i dettagli degli ordini, cosiddetta "data table"
ADV_Products_LUT -> tabella contenente i dettagli dei prodotti, cosiddetta "look up table"
ProvinceItaliane_LUT -> tabella contenente i dettagli relativi alle province italiane, cosiddetta "look up table"

L'esercizio da svolgere è il seguente:
Trovare l'incidenza percentuale delle fatturato delle vendite per quei prodotti il cui prezzo e maggiore della media dei prezzi di tutti i prodotti, suddiviso per provincia.

Dobbiamo quindi trovare:
1- La somma del fatturato di tutti i prodotti venduti
2- La media dei prezzi di tutti i prodotti.
2- La somma del fatturato dei soli prodotti venduti il cui prezzo è > della media dei prezzi di ogni prodotto

ed infine dividere i due risultati tra loro in modo da trovare l'incidenza percentuale %.

Vado quindi ad instanziare una matrice dove inserisco come ROWS il dato Città e come primo campo VALUES la seguente measure:

Codice: Seleziona tutto

SALES_AMOUNT = SUMX(Sales,Sales[Quantità_Ordinata]*RELATED(ADV_Products_LUT[Prodotto_Prezzo]))
Andiamo prima a vedere, per chi come me ha più facilità di apprendimento in maniera visuale, cosa succede a grandi linee tra le tabelle dati che abbiamo (ho modificato il file excel in modo che contenesse tutti gli ordini, le città relative e il prezzo unitario del prodotto)
Abbiamo innanzitutto un FILTER CONTEXT che è uguale a alle nostre Città:

Step 1 - La tabella di partenza
Immagine
Step 2 - La tabella viene filtrata per ogni città, nell' esempio "Cagliari" (filter context)
Immagine
Step 3 - Tramite la funzione RELATED viene relazionato il prezzo al prodotto
Immagine
Step 4 - Viene applicata l' espressione contenuta nella funzione SUMX
Immagine
Step 5 - Infine viene applicata la somma sui valori risultanti dall' espressione
Immagine

Come vediamo, il risultato è lo stesso di quello calcolato all'interno della matrice di POWER BI, ovviamente vengono calcolate anche le somme per tutte le altre città.

Fin qui abbastanza semplice, abbiamo trovato la somma di tutti i prodotti venduti suddivisi per provincia.

Passiamo ora a calcolare la media dei prezzi di prodotti, anche questo è abbastanza facile:

Codice: Seleziona tutto

AVERAGE_PRODUCT_PRICE = average(ADV_Products_LUT[Prodotto_Prezzo])
Immagine

Il risultato è 714.44. Se proviamo a mettere questa measure tra le VALUES della matrice, noteremo che ci verrà restituito sempre lo stesso risultato, contrariamente a quanto magari qualcuno potrebbe pensare (non vi è alcuna relazione diretta tra la tabella prodotti e la tabella città, non otterrò quindi il prezzo medio dei prodotti venduti a "Cagliari").

Detto ciò, abbiamo il totale venduto per provincia ed il prezzo medio. Andiamo a recuperare il totale venduto di quei prodotti il cui prezzo è maggiore del prezzo medio di tutti i prodotti.

Quello che vogliamo è pertanto:
1- Per ogni provincia
2- Sommare il prodotto tra le quantità vendute x il prezzo unitario
3- Solo per quei prodotti
4- Maggiori di 714.44.

Quindi la nostra formula ipotetica sarebbe qualcosa del tipo sum(quantità*prezzo) where prezzo > prezzo_medio

Tradotto in DAX:

Codice: Seleziona tutto

CALCULATE(SUMX(Sales,Sales[Quantità_Ordinata]*RELATED(ADV_Products_LUT[Prodotto_Prezzo])),ADV_Products_LUT[Prodotto_Prezzo]>average(ADV_Products_LUT[Prodotto_Prezzo]))
Che possiamo semplificare, avendo già le measure definite così:

Codice: Seleziona tutto

CALCULATE([SALES_AMOUNT],ADV_Products_LUT[Prodotto_Prezzo]>[AVERAGE_PRODUCT_PRICE])
PROBLEMA!
Non è possibile utilizzare una measure nell' argomento filtro della funzione CALCULATE, quindi l' espressione dax sopra indicata andrà in errore.
Per poter utilizzare la measure nell' argomento filtro dobbiamo utilizzare la funzione FILTER (che viene utilizzata da POWER BI dietro le quinte normalmente per le normali espressione che non la utilizzano).

DOVE NON CAPISCO COSA SUCCEDE
Quindi procediamo:

Codice: Seleziona tutto

CALCULATE([SALES_AMOUNT],FILTER(ADV_Products_LUT,ADV_Products_LUT[Prodotto_Prezzo]>[AVERAGE_PRODUCT_PRICE]))
Inserendo questa measure nella nostra matrice, non otteniamo il risultato sperato, anzi, non viene restituito alcun valore.

Conosco già le soluzioni al problema ne ho ben due:
1- Costruire la measure AVERAGE_PRODUCT_PRICE nel seguente modo:

Codice: Seleziona tutto

CALCULATE(AVERAGE(ADV_Products_LUT[Prodotto_Prezzo]),all(ADV_Products_LUT))
In questo modo, "decontestualizziamo" la misura (il mio problema è che non ho capito cosa la contestualizza se non la scrivo in questo modo)

2- Utilizzando una variabile, la quale non ho ancora studiato ma sembra decontestualizzi o comunque "fissi" il valore di un espressione:

Codice: Seleziona tutto

VAR _AvgPrice = DAX.Average_Products_Price
RETURN
    CALCULATE (
        [DAX.Sales_Amount],
        FILTER ( ADV_Prodotti_LUT, ADV_Prodotti_LUT[Prodotto_Prezzo] > _AvgPrice )
    )
​
Ora quello che secondo me dovrebbe avvenire (e che evidentemente non accadde) sono i seguenti step:

1- La mia tabella viene prima filtrata per il filter context, sempre per ogni città, successivamente ad ogni riga viene applicata l' espressione di filtraggio

Immagine

2- La tabella viene filtrata ulteriormente solo per i valori cui risultato dell' espressione di filtraggio è TRUE


Immagine

3- Viene quindi applicata l' espressione per ogni riga, ed infine eseguita la somma (sumx), restituendo correttamente quanto ricercato

Immagine


Mi è stato detto che la mia formula che ritorna l' AVERAGE non ritorna più 714.44 bensì lo stesso prezzo del prodotto per ogni riga prodotto e quindi la condizione di filtraggio non è mai soddisfatta e non viene ritornato niente. Ok ha senso, non faccio fatica a capire questo, ne che la mia average venga eseguita riga per riga, quello che non capisco è perché non faccia più la media su tutte le righe dei prodotti ma solo su quella che si sta iterando (sempre ammesso che sia questo ciò che avviene) ... Io eseguo l' average per ogni riga e per me questo significa essere in un row context, ma poi non mi immagino che anche la mia measure effettui calcoli solo utilizzando come source quell' unica riga...

Vi sarò molto grato se riuscite a spiegarmi ciò, forse penso di aver capito cosa sia il row context quando non è così ....


Avatar utente

Andrea90
Messaggi: 2318 | Topic creati
Iscritto il: dom 28 giu 2020, 19:41
Luogo: Bologna
Ringraziato: 677 volte
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Andrea90 »

Ciao Mohican1989,

Ti ringrazio per aver utilizzato questo forum :thumbup:

Per quel che riguarda la tua domanda, al quale ho visto che hai già individuato una soluzione pratica, ma ti serve una spiegazione sul motivo per la quale la tua formula originaria non funziona. Che da quel che ho capito risulta essere questa (correggimi se sbaglio):

Codice: Seleziona tutto

CALCULATE([SALES_AMOUNT],FILTER(ADV_Products_LUT,ADV_Products_LUT[Prodotto_Prezzo]>[AVERAGE_PRODUCT_PRICE]))
Dove la formula non funziona poiché quando usi un FILTER come argomento filtro di un calculate è come se gli stessi passando una lista di valori (in questo caso provenienti dalla tua tabella ADV_Products_LUT), da aggiungere al contesto valutativo per calcolare l'espressione posta al primo argomento. (in realtà DAX utilizza sempre un FILTER come argomento filtro, anche se usi un espressione TRUE/FALSE come quella che hai indicato)

Ora siccome il filter itera la tabella ADV_Products_LUT utilizzando un calcolo iterativo, e cioè riga per riga, [AVERAGE_PRODUCT_PRICE] sarà sempre uguale al prezzo del prodotto posto alla riga corrente, ed il prezzo non può essere maggiore di se stesso e dunque la lista per la quale filtrare l'espressione risulterà vuota e dunque ecco il motivo per la quale, scritta in questo modo, la formula non funziona (per fare una prova invece che solo maggiore scrivi >= e vedrai che ti riporterà l'ammontare totale delle vendite). Tutto questo perchè si attiva il context transition e dunque quella riga che tu iteri (tramite FILTER) diventa a sua volta un filtro (poichè il row context si trasforma in un filter context), ed essendo la tabella iterata, una tabella LOOKUP (con soli valori univoci), ogni riga iterata riporterà, a seguito del filtro, solo se stessa.

Dunque, come hai suggerito tu stesso, una possibile soluzione risulta essere:

Codice: Seleziona tutto

 = CALCULATE([SALES_AMOUNT],FILTER(ADV_Products_LUT,ADV_Products_LUT[Prodotto_Prezzo]>[COURSE AVERAGE_PRODUCT_PRICE]))
Come vedi le due formule sono praticamente identiche tranne che questa volta la media viene calcolata tramite un calculate che ha al suo interno un ALL() basato sull'intera tabella ADV_Products_LUT, e dunque calcolerà sempre la media, indipendentemente dai filtri che andrai ad apporre relativi a questa tabella.

Spero di poter aver reso più chiara l'idea, nel caso scrivi pure i dubbi rimasti.

Appena mi è possibile proverò a risponderti, o ancora meglio, lo faranno gli altri utenti :thumbup:

A presto,

Andrea
Se hai gradito l'aiuto che hai ricevuto considera di contribuire alle spese per il mantenimento del forum facendo una libera DONAZIONE --> Link

Ricordarsi di segnare come "RISOLTE" le discussioni per le quali si è ricevuto un feedback positivo. Per vedere come fare --> Link
Avatar utente

Enrico Galli
Messaggi: 890 | Topic creati
Iscritto il: dom 28 giu 2020, 19:03
Luogo: San Giovanni in Persiceto (BO)
Ringraziato: 325 volte
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Enrico Galli »

Ciao Mohican1989, innanzi tutto grazie e complimenti per il tempo che hai dedicato nel rendere il tuo quesito più completo e dettagliato possibile, con immagini, allegato e passaggi spiegati così accuratamente :clap:

Aggiungo una mia spiegazione a quella, naturalmente ottima e corretta, di Andrea90 :
quello che non capisco è perché non faccia più la media su tutte le righe dei prodotti ma solo su quella che si sta iterando (sempre ammesso che sia questo ciò che avviene) ... Io eseguo l' average per ogni riga e per me questo significa essere in un row context, ma poi non mi immagino che anche la mia measure effettui calcoli solo utilizzando come source quell' unica riga
Il meccanismo che ancora non ti è chiaro, e che è tra i più complessi da capire e "interiorizzare" del DAX, è quello della context transition.
Prendiamo la misura che utilizzi tu:

Codice: Seleziona tutto

CALCULATE(
    [SALES_AMOUNT],
    FILTER(
        ADV_Products_LUT,
        ADV_Products_LUT[Prodotto_Prezzo]>[AVERAGE_PRODUCT_PRICE]
    )
)
FILTER, come saprai, è un iteratore. In quanto tale, al suo interno si crea un row context. C'è però anche una cosa che non vedi: attorno a [AVERAGE_PRODUCT_PRICE], che è una misura, c'è un costrutto che viene aggiunto implicitamente dal DAX quando utilizzi una misura in un row context, e questo costrutto è CALCULATE. Quindi, la funzione sarebbe da leggere così:

Codice: Seleziona tutto

CALCULATE(
    [SALES_AMOUNT],
    FILTER(
        ADV_Products_LUT,
        ADV_Products_LUT[Prodotto_Prezzo]>CALCULATE([AVERAGE_PRODUCT_PRICE])
    )
)
CALCULATE ha una caratteristica: "distrugge" tutti i row context esistenti durante la sua esecuzione, e li "trasforma" in filter context. Come avviene questo? Praticamente, CALCULATE prende il row context (ovvero i valori presenti nella riga che FILTER sta iterando in quel momento), e con essi costruisce un filter context, che sarà composto dai valori stessi per le rispettive colonne. Su questo NUOVO filter context, CALCULATE valuterà l'espressione e restituirà il risultato. Molto spesso (ma non necessariamente), questo significa che il nuovo filter context sarà costituito da quell'unica riga della tabella iterata. Dico non necessariamente, perché se in questa tabella ci dovessero essere delle righe duplicate, il filter context le includerebbe, facendo i calcoli (media, somma, o quello che sia) su di esse.

Pertanto, schematizzando, cosa succede?
1) FILTER itera riga per riga
2) Su questa riga viene valutato se un campo è > di una misura
3) interviene CALCULATE che innesca la context transition, calcolando questa misura per le sole righe "identiche" a quella che stiamo iterando
4) il valore viene quindi confrontato nella maggior parte dei casi con sé stesso, e nel tuo esempio fa fallire i presupposti di fondo.

Perché inserendo il valore in una VAR funziona?
Perché la VAR viene valutata sul contesto attivo in quel momento, e poi resta immutata per il resto del calcolo. E se tu la metti all'inizio, FILTER non è ancora stato attivato, quindi non c'è alcun row context, non si innesca la context transition e il valore memorizzato nella VAR è quello che tu ti aspetti. Quando poi lo riusi all'interno del FILTER, è diventato uno scalare, proprio come immaginavi tu: non viene valutato ulteriormente, CALCULATE non può nulla, e tutto funziona.

Spero di averti chiarito ancora un po' le idee, in caso contrario rileggi :D e soprattutto prova e riprova... ci va un po' di tempo, ma piano piano il cervello si abitua a ragionare "in linguaggio CALCULATE" e tutto ti verrà più naturale. Mi raccomando facci sapere, e a presto! :wave:
Enrico Galli
Link utili: I nostri tutorial | Come inserire: Immagini - Codice - Risolto
Se il forum ti è stato utile, considera di supportarlo con una libera donazione
Avatar utente

Autore del topic
Mohican1989
Messaggi: 8 | Topic creati
Iscritto il: ven 10 lug 2020, 16:40
Ringraziato: 1 volta
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Mohican1989 »

Buonasera,
intanto ringrazio entrambi per la solerzia nell'avermi risposto e mi scuso per non essere stato altrettanto tempestivo, so bene che chi da un contributo si aspetta un riscontro ma non volevo essere affrettato nel darlo.

Ammetto che mi sono riletto più volte entrambe le risposte, significative sono state le informazioni riguardo l'aggiunta "nascosta" di CALCULATE quando si utilizza una MEASURE e il context transition di cui mio malgrado non ero a conoscenza (il corso che seguo probabilmente copre in un momento successivo il tema in maniera approfondita ma, dovendo svolgere un esercizio del genere, sarei curioso di sapere se chi è alle prime come me abbia davvero "capito" come affrontare l' esercizio, dal momento che non ritengo che lo si possa svolgere con cognizione di causa).

Mi sono quindi riletto con una visione più ampia https://www.sqlbi.com/articles/row-cont ... xt-in-dax/ e https://www.sqlbi.com/articles/understa ... ransition/.
Quest'ultimo è articolo da cui non avevo ancora attinto non conoscendo il concetto di context transition.

In questo in particolare viene ben evidenziato quanto da entrambi esposto, quindi il funzionamento del context transition, dell' "hidden calculate" davanti a una misura e viene fatto un piccolo accenno all' uso di VAR.

Dopo questo ho provato a braccio a ricreare una formula e ho "trovato" (più a verificare se quanto letto è stato lontanamente appreso,ci sarebbero penso molti altri modi) un altra soluzione, sicuramente meno elegante, ma che evidenzia come l'uso di un espressione dax non già definita come MEASURE cambi del tutto il risultato che si viene ad ottenere.
Al posto quindi di utilizzare la MEASURE AVERAGE_PRODUCT_PRICE (senza calculate/all) o la MEASURE COURSE_AVERAGE_PRODUCT_PRICE (che è costruita con calculate/all) posso riscrivere la mia espressione originale senza dover "eliminare" filtri in quanto, non essendoci il calculate nascosto davanti, non avviene nessun context transition:

Codice: Seleziona tutto

CALCULATE([SALES_AMOUNT],FILTER(ADV_Products_LUT,ADV_Products_LUT[Prodotto_Prezzo]>average(ADV_Products_LUT[Prodotto_Prezzo])))
Sicuramente dovrò "allenare" la testa a pensare quali contesti e transizioni avvengono mentre scrivo un espressione DAX ma sono sicuro che col tempo tutto verrà più naturale.
Aggiungerò successivamente qualche "immagine" al post in modo da "fissarmi" i passaggi nella mente ed aiutare altri che potrebbero trovarlo utile.

Vi ringrazio molto in quanto ora, posso continuare il mio corso con consapevolezza (la mia pecca è che quando non capisco qualcosa mi blocco e mi rifiuto di andare avanti finché ho chiarito come funzionano le cose), dopo quasi 2 settimana che ho provato a leggere a destra e a manca senza trovare la soluzione :clap:
Avatar utente

Enrico Galli
Messaggi: 890 | Topic creati
Iscritto il: dom 28 giu 2020, 19:03
Luogo: San Giovanni in Persiceto (BO)
Ringraziato: 325 volte
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Enrico Galli »

Mohican1989 ha scritto: lun 13 lug 2020, 2:10 Dopo questo ho provato a braccio a ricreare una formula e ho "trovato" (più a verificare se quanto letto è stato lontanamente appreso,ci sarebbero penso molti altri modi) un altra soluzione, sicuramente meno elegante, ma che evidenzia come l'uso di un espressione dax non già definita come MEASURE cambi del tutto il risultato che si viene ad ottenere.
Al posto quindi di utilizzare la MEASURE AVERAGE_PRODUCT_PRICE (senza calculate/all) o la MEASURE COURSE_AVERAGE_PRODUCT_PRICE (che è costruita con calculate/all) posso riscrivere la mia espressione originale senza dover "eliminare" filtri in quanto, non essendoci il calculate nascosto davanti, non avviene nessun context transition
Intanto grazie per il feedback e la condivisione :thumbup:
Vorrei ampliare ulteriormente il discorso, sperando di non confondere le idee: la tua soluzione è sostanzialmente equivalente a quella che abbiamo suggerito con l'utilizzo della variabile, ed evita come hai giustamente detto tu l'intervento della context transition (a ulteriore riprova di quanto spiegato in precedenza, prova a mettere un CALCULATE intorno alla tua condizione AVERAGE() e tornerai al problema iniziale :idea: ).

Queste due soluzioni danno lo stesso risultato di quella proposta nel corso, ma solo nel caso in cui il filter context non influisca sul calcolo della media. Come hai giustamente osservato, infatti, la tabella delle province non è in relazione con la tabella prodotti e quindi non la filtra. Ma guarda cosa succede se al posto delle province ci mettiamo il colore del prodotto:

Immagine

Le prime due misure "high ticket" sono la tua e quella con VAR. La terza è quella del corso, e come vedi i risultati sono diversi. Perché? Perché nelle prime due misure, il calcolo della media è influenzato dal filter context: finché questo non incide sulla tabella prodotti, nulla cambia; ma inserendo in riga una variabile che filtra la tabella prodotti, il calcolo della media sarà limitato a questo sottoinsieme di righe della tabella.
Nella misura proposta nel corso, invece, ci si accerta che il filter context non abbia effetto, poiché il calcolo della media avviene su ALL(Prodotti), ovvero viene annullato qualsiasi filtro proveniente dall'esterno. Pertanto, come vedi dalle ultime due colonne, il risultato della media calcolata in questo modo non varierà, al contrario di prima.

Attenzione: non necessariamente in questo caso si può stabilire quale sia la soluzione "giusta": può essere infatti che tu voglia calcolare la quota di prodotti ad alto valore relativamente al singolo colore, quindi superiori alla media dei prodotti di quel colore, oppure vedere quanti prodotti di quel colore superano come prezzo la media complessiva dei prodotti. Tuttavia le differenze in alcuni casi sono marginali, e sarebbe stato difficile individuarle a occhio nudo, perciò bisogna fare molta attenzione. Si tratta sempre di capire qual è il risultato atteso dell'analisi, e quali strumenti usare per ottenerlo :wave:
Enrico Galli
Link utili: I nostri tutorial | Come inserire: Immagini - Codice - Risolto
Se il forum ti è stato utile, considera di supportarlo con una libera donazione
Avatar utente

Autore del topic
Mohican1989
Messaggi: 8 | Topic creati
Iscritto il: ven 10 lug 2020, 16:40
Ringraziato: 1 volta
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Mohican1989 »

La parte più difficile è chiaramente "accorgersi" di questi dettagli, pensare a quali contesti sono gioco e conoscere bene le relazioni tra le tabelle dati. Mi pare di aver capito, sempre dalle ultime lette che il filter context si propaga alle tabelle relazionate. Mi sorge quindi una domanda, il filter context, agisce fino al livello "più nested" di una formula (o è meglio dire, ad ogni formula?) ? Quando valutate nella vostra mentre un espressione, mi viene in mente in excel, parto dalla più annidata e risalgo la stessa. Questo è un approccio sbagliato in quanto se dovessi valutare average senza considerare il contesto i passaggi sarebbero errati.

Riprendendo l' esempio di una matrice con i colori del prodotto la formula previamente utilizzata (che restituisce un risultato "sbagliato" in questo caso) sarebbe:

Codice: Seleziona tutto

CALCULATE(sumx(sales,Sales[Quantità_Ordinata]*RELATED(ADV_Products_LUT[Prodotto_Prezzo])),FILTER(ADV_Products_LUT,ADV_Products_LUT[Prodotto_Prezzo]>AVERAGE(ADV_Products_LUT[Prodotto_Prezzo])))
Il filter context "attraversa" tutta la formula fino alla funzione AVERAGE che viene valutata vs la tabella Products filtrata appunto dal filter context.
Così facendo viene calcolata solo la media dei prezzi di quei prodotti il cui colore è dell' attuale filter context, modificando ovviamente il risultato.

Quindi per ovviare è indispensabile questa volta far uso della funzione CALCULATE() a circondare la funzione AVERAGE(), indicando nel filtro la funzione ALL() in modo da eliminare 1 o più filtri applicati (siano essi filter o row context trasformati in filter).

Codice: Seleziona tutto

CALCULATE(sumx(sales,Sales[Quantità_Ordinata]*RELATED(ADV_Products_LUT[Prodotto_Prezzo])),FILTER(ADV_Products_LUT,ADV_Products_LUT[Prodotto_Prezzo]>CALCULATE(AVERAGE(ADV_Products_LUT[Prodotto_Prezzo]),ALL(ADV_Products_LUT))))
Possiamo in definitiva dire che, usare CALCULATE/ALL è "più sicuro" nell' ottica di voler avere come risultato un valore scalare "puro" non affetto da contesti vari, mentre l' utilizzo di VAR per il nostro esempio funziona solo in quanto alla sua definizione non era stato ancora definito alcun row context (inizializzato da FILTER) e non esisteva un filter context (che esiste comunque prima della definizione della MEASURE).
Avatar utente

Andrea90
Messaggi: 2318 | Topic creati
Iscritto il: dom 28 giu 2020, 19:41
Luogo: Bologna
Ringraziato: 677 volte
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Andrea90 »

Ciao Mohican1989,

Non è immediata la risposta alla tua domanda, nel senso che con DAX le generalizzazioni lasciano il tempo che trovano poiché è un linguaggio estremamente delicato, che richiede molte considerazioni per testare la validità di una misura.

Prendiamo ad esempio la tua formula:

Codice: Seleziona tutto

=
CALCULATE (
    SUMX (
        sales,
        Sales[Quantità_Ordinata] * RELATED ( ADV_Products_LUT[Prodotto_Prezzo] )
    ),
    FILTER (
        ADV_Products_LUT,
        ADV_Products_LUT[Prodotto_Prezzo]
            > AVERAGE ( ADV_Products_LUT[Prodotto_Prezzo] )
    )
)
La funzione CALCULATE come saprai è una funzione che agisce al contrario, nel senso che prima valuta l'argomento filtro (in questo caso la formula FILTER) e successivamente valorizza l'espressione posta al primo argomento sulla base del contesto filtro modificato (modificato dall'argomento filtro)

Inoltre ricordati che il contesto filtro, altro non fa che filtrare le tabelle per le quali andrai a valorizzare una misura. Faccio un esempio, se hai un report con i colori posti per riga allora ogni singola riga di questa tabella è un contesto filtro a sé stante. Infatti ogni valore associato alla dimensione [Colore] andrà a filtrare la tabella che contiene la misura da aggregare (ad esempio le vendite) e di sole quelle righe rimaste andrà ad effettuare il calcolo desiderato (ad esempio la somma).

In questo caso tu hai una formula FILTER() la quale è una formula iterativa che prende le righe di una tabella ed "elimina" tutte quelle che non soddisfano la condizione posta come secondo argomento. La tabella che va ad iterare (così come l'hai scritta) è influenzata dal contesto filtro, infatti se stai usando una tabella suddivisa per colori, con il colore Rosso come primo valore, e di prodotti con il colore rosso ce ne sono 5, allora quella tabella ADV_Products_LUT non conterrà tutte le righe della tabella originale, ma solo quelle 5 filtrate, a cui tu poi vai ad aggiungere una condizione ulteriore per filtrare.

Caso diverso invece era se tu avessi richiamato come primo argomento della funzione FILTER la formula ALL(ADV_Products_LUT), in questo modo avresti eliminato il contesto filtro che agiva sulla tabella (quello che ti portava a considerare per il colore rosso solamente 5 righe).

A questo punto la lista di righe che ti rimangono a seguito dell'operazione FILTER vanno a creare un nuovo contesto filtro che agirà sull'espressione posta come primo argomento (la quale contiene un calcolo iterativo sulla tabella Sales).

Purtroppo non credo sia possibile darti una risposta completa a 360 gradi poiché gli argomenti da considerare sarebbero davvero tanti (ad esempio il concetto di Expanded Table che non ho nemmeno accennato). Il consiglio è quello di continuare a provare e a studiare. Troverai dei riferimenti bibliografici utili del buon Enrico Galli nella sezione Libri.

Prima costruisciti la base con libri (video) più semplici, ed infine comincia a studiare la Definitive Guide to Dax Second Edition.

Ti arriveranno sicuramente altri input da altri utenti. Prova a rivederli tutti nel loro insieme e poi se hai ancora ulteriori dubbi chiedi pure.

A presto,

Andrea
Se hai gradito l'aiuto che hai ricevuto considera di contribuire alle spese per il mantenimento del forum facendo una libera DONAZIONE --> Link

Ricordarsi di segnare come "RISOLTE" le discussioni per le quali si è ricevuto un feedback positivo. Per vedere come fare --> Link
Avatar utente

Enrico Galli
Messaggi: 890 | Topic creati
Iscritto il: dom 28 giu 2020, 19:03
Luogo: San Giovanni in Persiceto (BO)
Ringraziato: 325 volte
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Enrico Galli »

Mohican1989 ti consiglio di fare questo esercizio di meditazione trascendentale :crazy: :mrgreen: ogni sera prima di addormentarti ripeti il mantra:
Il filter context filtra, il row context itera. Il row context non filtra, il filter context non itera
Scherzi a parte, questa è una delle regole auree del DAX.
Il filter context, che è costituito da tutti i campi che filtrano il tuo report, più tutti i filtri esterni (slicer, filtro rapporto, filtro pagina, filtri da altre visualizzazioni), filtra tutto il report, e ogni parte di tutte le funzioni che scrivi. Un po' come in una tabella pivot classica, dove i numeri che vai a sommare (o contare, etc.) risentono di quello che appare in riga, in colonna, nel filtro e negli slicer. Questo è il filter context.

Vi sono delle funzioni che consentono di ignorare il filter context o parte di esso (es. ALL), ma soltanto una può modificarlo; hai indovinato, è la regina di tutte le funzioni: CALCULATE (e la sua omologa CALCULATETABLE). Quello che tu scrivi nell'argomento filtro di CALCULATE viene letto in questo modo: "me ne frego di tutto quello che c'è nel filter context: per questo calcolo decido io qual è il filter context e vado giù dritto come il piombo". Per questa ragione, nella misura scritta con CALCULATE(misura, ALL(tabella)), il risultato non cambia mai, qualunque sia il filter context di quella "cella".
Enrico Galli
Link utili: I nostri tutorial | Come inserire: Immagini - Codice - Risolto
Se il forum ti è stato utile, considera di supportarlo con una libera donazione
Avatar utente

Autore del topic
Mohican1989
Messaggi: 8 | Topic creati
Iscritto il: ven 10 lug 2020, 16:40
Ringraziato: 1 volta
Contatta:

Formule Dax - Filter Context / Row Context - Problema con esempio

Messaggio da Mohican1989 »

Grazie a entrambi, scusate ma è stata una settimana di inferno e mettermi al pc era un fatica.

Ho sicuramente appreso molto già da questa spiegazioni e "hints" ne farò tesoro ;)
Rispondi