EN

Mise en place voor DAX: measure of berekende kolom?

🎯 Beginner⏱ 10 minuten

Wat je in deze les leert

Twintig jaar horeca heeft me één onderscheid bijgebracht dat overal geldt: sommig werk moet uren vooraf gedaan worden, anders bindt het niet, rijst het niet, zit het niet goed. Ander werk kun je pas doen op het moment dat de gast er zit, want een steak die je twee uur eerder doorbakt is geen steak meer bij het opdienen, en opgeklopte slagroom die een uur in de koelkast heeft gestaan heb je niet nodig aan tafel. Twee categorieën, allebei noodzakelijk, allebei mise en place in de brede zin: klaarzetten voor het moment waarop het nodig is. Alleen het moment verschilt.

Bij DAX werkt het precies zo. Er zijn berekeningen die thuishoren bij model refresh, eenmalig uitgerekend en opgeslagen, klaar en wachtend. Er zijn berekeningen die je pas kunt doen op het moment dat iemand een filter aanraakt, een slicer beweegt of een visual opent. Die twee categorieën heten berekende kolom en measure, en de vraag welke is wat is precies de vraag waar bijna elke beginner op dag twee van een DAX-cursus op vastloopt.

Waarom de verkeerde keuze zo aantrekkelijk voelt

De trek naar een berekende kolom is begrijpelijk. Je typt je formule, je drukt op enter, en de uitkomst staat meteen in de tabel, rij voor rij. Dat voelt als voortgang, net als groentes die je 's ochtends hebt voorgesneden en netjes in bakjes hebt gezet. Je ziet wat je hebt gemaakt, het staat er gewoon.

Het probleem is dat een berekende kolom ook echt zo werkt: hij denkt per rij en ziet de tabel niet als geheel. Vraag hem om een totaal te berekenen, een marge over een selectie te geven of een aandeel van de zichtbare set te tonen, en hij kijkt alleen naar zijn eigen rij. Het getal dat hij geeft is niet het getal dat de gebruiker verwacht in de visual. Die mismatch is een van de meest voorkomende bronnen van DAX-verwarring, en hij ontstaat doordat iemand een filtercontext-berekening in een kolom heeft gezet in plaats van in een measure.

Berekende kolom: klaargezet bij refresh

Een berekende kolom wordt geëvalueerd tijdens data refresh of model load, per rij van de tabel, in row context. De uitkomst wordt opgeslagen in het semantic model en neemt geheugen in. Tot de volgende refresh staat de waarde vast, voor iedereen die het rapport bekijkt hetzelfde.

Gebruik een berekende kolom voor waardes per rij die je later als filter, categorie of schakel in een relatie nodig hebt. Klantsegment op basis van omzet: de kolom kijkt naar de omzetwaarde van elke rij en kent er een label aan toe, klaar voor een slicer. Leeftijdscategorie op basis van geboortedatum: uitgerekend bij refresh, zodat een slicer er later aan kan binden. Jaarlaag op basis van orderdatum: zelfde logica. Als die kolom er niet staat bij refresh, heeft een slicer niets om aan te binden en een relatie niets om op te leunen.

De mise-en-place-vergelijking klopt op dit punt precies: het staat klaar voordat de dienst begint, voor iedereen die dag hetzelfde.

Measure: uitgerekend op het vraagmoment

Een measure wordt niet opgeslagen. Hij bestaat als formule in het model, en hij wordt pas uitgerekend op het moment dat iemand een visual bekijkt, een slicer aanraakt of doorklikt op een categorie. Telkens opnieuw, onder de filtercontext die dat moment meebrengt: welke regio heeft de gebruiker geselecteerd, welk jaar staat in de slicer, welke categorie is actief?

Totaal in de huidige selectie, marge in het gekozen jaar, aandeel van de zichtbare set: dat zijn per definitie vragen die met elke interactie veranderen. En daarom horen aggregaties (SUM, AVERAGE, COUNTROWS) altijd in een measure. Je kunt ze in een berekende kolom zetten, maar dan krijg je niet het getal dat je verwacht, want de kolom denkt per rij en ziet het geheel niet.

Checkvraag

Je zet SUM(Orders[Bedrag]) in een berekende kolom. Wat krijg je?

De vraag die de keuze makkelijk maakt

📌
Onthoud dit

Default naar een measure. Kies pas bewust voor een berekende kolom als je een waarde per rij nodig hebt die later als filter, categorie of relatie moet dienen.

De beslissende vraag is simpel: op welk moment moet deze berekening antwoord geven? Bij refresh, als een vaste waarde per rij die als filter of categorie dient? Dan een berekende kolom. Op het moment dat iemand het rapport bekijkt, als een aggregaat dat meebeweegt met de selectie? Dan een measure. Stel die vraag hardop voordat je begint te typen, en de keuze wordt bijna altijd vanzelf duidelijk. Modellen die op die manier zijn gebouwd, zijn lichter en geven betrouwbare totalen: twee dingen die je pas mist als ze ontbreken.

Oefen de timingvraag hieronder: zes berekeningen uit de praktijk, en per kaart kies je het moment waarop hij thuishoort.

Sorteeropdracht

Refresh of vraagmoment: waar hoort deze berekening?

Volgende in de DAX-basis: SUM, COUNTROWS en DISTINCTCOUNT, de drie functies die iedereen kent en waarvan de helft toch niet doet wat je denkt.

Wil je de DAX-basis samen doorlopen of je eigen vragen bespreken? Kijk op trainerbjorn.nl.

TrainerBjörn is onderdeel van DoGoDa, Doing Good with Data. Gemaakt door Björn, met hulp van AI. Disclaimers.