Salta al contenuto

Come mostrare i valori di una misura soltanto in assenza di valori BLANK( ) – caso non additivo

In due precedenti articoli, il primo disponibile qui, il secondo qui, è stato illustrato come mostrare i valori di una misura soltanto quando essa abbia valori non BLANK in tutti gli anni del calendario (primo articolo) o in una selezione degli stessi anni effettuata dall’utente attraverso uno slicer (secondo articolo).

In coda al primo articolo erano stati segnalati due punti di possibili miglioramento, sul primo punto (permettere all’utente di selezionare gli anni) è stato posto rimedio con il secondo articolo, sul secondo punto si lavorerà in questo articolo.

Il secondo punto poneva una questione sottile: l’assunzione dell’additività. In effetti, spesso, questo aspetto viene trascurato dai designer di DAX. Nel primo e secondo articolo, è stata data per scontata, cioè, una misura additiva. Una misura additiva è una misura che, se calcolata in assenza di filtri, fornisce un valore pari alla somma dei suoi valori in presenza di filtri. Per esempio, sezionando una visual anno per anno (inserendo, cioè, il campo Anno[Anno] in riga), se una misura è additiva, il suo valore al totale sarà pari alla somma dei valori in corrispondenza di ogni anno. Per esempio, la misura QTY = SUM ( Dati[Qtà] ) è additiva e così si è potuto sviluppare la soluzione usando una SUMX che calcolava la misura QTY per ogni azienda e anno, sommando alla fine i risultati per ottenere il valore richiesto. In quest’ultimo passaggio è stata assunta l’additività come precondizione.

Che succede, invece, nel caso in cui lo stesso approccio sia usato con una misura non additiva? Il classico esempio è una misura che usi la funzione DISTINCTCOUNT. Per potere mostrare il problema e risolverlo, sono state modificate le tabelle del modello rispetto ai primi due articoli, aggiungendo una colonna alla tabella Dati, Dati[Prodotto], che permette di usare DISTINCTCOUNT ottenendo un risultato non additivo. Il modello e le relative tabelle sono visibili nelle figure a seguire. In figura 1 è mostrato il modello, con evidenziata la nuova colonna aggiunta.

Figura 1

Sono state definite due misure, Num Prodotti e Num Prodotti tutti gli anni selezionati, dal seguente codice:

Num Prodotti =
DISTINCTCOUNT ( Dati[Prodotto] )
Num Prodotti tutti gli anni selezionati =
VAR TuttiGliAnniSelezionati =
    COUNTROWS (
        ALLSELECTED ( Anno[Anno] )
    )
RETURN
    SUMX (
        VALUES ( Azienda[Azienda] );
        VAR AnniSelezionatiAziendaCorrente =
            COUNTROWS (
                FILTER (
                    ALLSELECTED ( Anno[Anno] );
                    NOT (
                        ISEMPTY (
                            CALCULATETABLE ( Dati )
                        )
                    )
                )
            )
        RETURN
            IF (
                AnniSelezionatiAziendaCorrente = TuttiGliAnniSelezionati;
                [Num Prodotti]
            )
    )

La misura Num Prodotti tutti gli anni selezionati segue la filosofia delle misure scritte nei due precedenti articoli, in cui si era assunta l’additività. In figura 2 il risultato delle due misure appena definite.

Figura 2

Si nota, in figura 2, la non additività (del tutto attesa) della misura Num Prodotti per i clienti A, C e D (non appare per B ma il discorso non cambia). La misura Num Prodotti tutti gli anni selezionati mostra gli stessi valori ma ci si focalizzi sul totale complessivo di questa misura: esso è pari a 8 che è pari allo somma dei valori di subtotale di ogni cliente in cui ci siano valori non vuoti (2 per A, 3 per C e 3 per D). Questo calcolo è errato.

Il meccanismo della misura Num Prodotti tutti gli anni selezionati non può essere corretto perché calcola il totale come somma dei subtotali cliente per cliente. Questo meccanismo era valido quando la misura era QTY tutti gli anni selezionati visto che la misura QTY è additiva (usa una SUM), adesso è in esecuzione Num Prodotti che usa una DISTINCTCOUNT.

Come risolvere il problema? La soluzione sta nel non pensare ad una somma di subtotali ma nell’esecuzione della misura nel giusto filter context. In sostanza bisogna chiamare la misura Num Prodotti dopo avere modificato il filter context nel modo opportuno, senza sommare di versi subtotali della stessa misura per ottenere il totale di Num Prodotti tutti gli anni selezionati. Il risultato desiderato è mostrato in figura 3.

Figura 3

Ecco il codice della misura Num Prodotti tutti gli anni selezionati OK per non additive che risolve il problema:

Num Prodotti tutti gli anni selezionati OK per non additive =
VAR TuttiGliAnniSelezionati =
    COUNTROWS (
        ALLSELECTED ( Anno[Anno] )
    )
VAR AziendeTuttiGliAnniSelezionati =
    FILTER (
        ADDCOLUMNS (
            VALUES ( Azienda[Azienda] );
            “@Anni”;
                CALCULATE (
                    DISTINCTCOUNT ( Dati[Anno] );
                    ALLSELECTED ( Anno[Anno] )
                )
        );
        [@Anni] = TuttiGliAnniSelezionati
    )
RETURN
    CALCULATE (
        [Num Prodotti];
        AziendeTuttiGliAnniSelezionati
    )

La chiave della soluzione è avere sostituito, al posto della chiamata a SUMX della misura Num Prodotti tutti gli anni selezionati, il calcolo della variabile AziendeTuttiGliAnniSelezionati: essa contiene le aziende che hanno la caratteristica di avere dati negli stessi anni selezionati dall’utente nello slicer. In questo modo si è fatto affidamento esclusivamente al filter context e non si è fatta alcuna assunzione di additività.

Dunque, questo approccio è più generico e, di conseguenza, in generale preferibile. Sulla difficoltà del codice, non ci sono differenza di difficoltà particolari tra la versione che considera l’additività come assunzione e quella più generica che abbiamo qui descritto, si tratta piuttosto di pensare in modo diverso: non una somma di subtotali ma un unico calcolo nel contesto corretto.

Conclusioni

Assumere l’additività è possibile quando essa è presente, tuttavia si rischia poi di riutilizzare il meccanismo sviluppato in ambiti dove essa non è valida, oltre al caso mostrato in questo articolo, si pensi ai calculation group dove il rischio è molto elevato potendo cambiare la misura oggetti del calcolo a piacimento, avvantaggiandosi dell’uso di SELECTEDMEASURE( ). Dunque, progettare senza assumere l’additività può essere un ottimo esercizio per praticare col DAX e una prassi certamente vantaggiosa.

Autore del Post

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *