Onsdag morgen. CFO'en igen:
"Jeg skal bruge det vigtigste tal: hvad var september-omsætningen?"
Du går til datasættet og leder efter en omsætningskolonne. Den findes ikke. Du har Antal, du har EnhedsPris, og du har Rabat. Du tænker: "Bare gang dem sammen og tag SUM."
Du prøver det første der falder dig ind:
Resultat: et astronomisk forkert tal. Det er den klassiske begynder-fælde.
Hvorfor er det forkert?¶
Lad os tage et minimalt eksempel - to ordrer:
| Ordre | Antal | Pris | Linjeomsætning (rigtig) |
|---|---|---|---|
| 1 | 2 | 100 | 200 |
| 2 | 3 | 50 | 150 |
| 5 | 150 | 350 |
Den rigtige omsætning er 350. Men SUM(Antal) * SUM(Pris) = 5 × 150 = 750. Mere end dobbelt så meget.
Problemet er at SUM aggregerer først, og gangen kommer bagefter. Det vi har brug for er det omvendte: gang først pr. række, summér derefter.
Det er præcis hvad SUMX gør.
SUMX - iteration over en tabel¶
X'et i SUMX står for "iterator". Funktionen går gennem tabellen række for række, beregner et udtryk i hver række, og lægger resultaterne sammen.
Syntaks¶
Løsningen¶
Hvad sker der her:
- SUMX går gennem hver række i
Salg. - I hver række beregnes
Antal × EnhedsPris × (1 - Rabat). - Resultatet for hver række lægges i en "bunke".
- SUMX returnerer summen af bunken.
Test: indsæt målet, træk det ind i et card-visual. Sammenlign med det forkerte mål - forskellen er drastisk.
Hvorfor ikke bare lave en beregnet kolonne?¶
Du kunne lave en beregnet kolonne på Salg:
Og så summere den:
Det virker. Men huskereglen fra modul 3 holder: undgå beregnede kolonner når et mål kan gøre det. Hver beregnet kolonne fylder i modellen, og store modeller bliver hurtigt seje. SUMX-versionen lever kun i øjeblikket og fylder ingenting.
Hvornår er en beregnet kolonne alligevel rigtig?
Hvis du har brug for at filtrere på linjeomsætning (fx via en slicer der hedder "ordrestørrelse" med intervaller), så skal det være en kolonne. En slicer kan ikke filtrere på et mål. Det er undtagelsen.
SUMX' familie¶
SUMX er ikke alene. Alle aggregeringer har en X-version:
| Almindelig | X-version | Bruges til |
|---|---|---|
| SUM | SUMX | Sum af et udtryk pr. række |
| AVERAGE | AVERAGEX | Gennemsnit af et udtryk pr. række |
| MAX | MAXX | Maksimum af et udtryk pr. række |
| MIN | MINX | Minimum af et udtryk pr. række |
| COUNT | COUNTX | Antal rækker hvor udtryk ikke er blank |
De fungerer alle på samme måde: første argument er tabel, andet er udtryk pr. række.
Performance - det er sandt at SUMX er langsommere¶
På et datasæt med 4.000 rækker mærker du intet. På 40 millioner rækker kan SUMX være sekunder langsommere end SUM på en præ-beregnet kolonne. Tommelfingerreglen:
- Måske 95% af tilfældene: Brug SUMX. Performance er ligegyldig på normale datasæt.
- De sidste 5% (store fakta-tabeller med tunge daglige rapporter): Overvej en beregnet kolonne.
Øvelse - bruttoavance¶
CFO'en spørger: "Hvad er den samlede bruttoavance?"
Antag at kostpris er 60% af enhedsprisen (vi har ikke en kostpris-kolonne, så vi simulerer). Bruttoavance pr. linje = Antal × EnhedsPris × (1 - Rabat) - Antal × EnhedsPris × 0,6.
Skriv målet selv.
Løsningsforslag
Bruttoavance =
SUMX(
Salg,
Salg[Antal] * Salg[EnhedsPris] * ( 1 - Salg[Rabat] )
- Salg[Antal] * Salg[EnhedsPris] * 0.6
)
Eller pænere - træk den fælles faktor ud:
Hvad du har lært¶
- SUMX itererer over en tabel og beregner pr. række før den summerer.
SUM(a) * SUM(b)er ikke det samme somSUMX(t, a * b)- det første aggregerer for tidligt.- Alle X-funktioner (AVERAGEX, MAXX, MINX...) virker på samme måde.
Næste problem: CFO'en vil se omsætning pr. kategori - og kategorien ligger i en helt anden tabel.