CK Labs — Head of Data & Analytics, Sephora
Formation Power BI
Module 5 sur 8 · DAX : cours + correction
Fil rouge : TheLook e-commerce
DAX : colonne vs mesure, DIVIDE, CALCULATE
Écrire ses propres indicateurs. La distinction colonne / mesure, les ratios propres avec DIVIDE, et le changement de contexte avec CALCULATE — appliqués aux mesures réelles de TheLook.
Module 5 / 8 DAX Mesures & calculs
Support 0
Intro
Pour qui, pourquoi Power BI, comment suivre.
Module 1
Le piège Excel
Pourquoi le reporting manuel vous enferme.
Module 2
Pourquoi Power BI
Le dernier kilomètre : de la donnée à la décision.
Module 3
Charger un fichier
Power Query : importer, nettoyer, fiabiliser.
Module 4
Découvrir & explorer
Métriques, dimensions, slicers, sanity check.
Module 5
DAX
Colonne vs mesure, DIVIDE, CALCULATE.
Module 6
Modélisation simple
Clés, cardinalité, schéma en étoile.
Module 7
Modélisation complexe
Multi-sources, calendrier, CAC / ROAS / budget.
Module 8
Récap & aide-mémoire
Fiches DAX, étoile, bonnes pratiques.
Bonus
Power BI & IA
L'ère agentique : piloter, mesurer, arbitrer.
À quoi sert ce module
Jusqu'ici, on a exploré des colonnes qui existaient déjà. DAX (Data Analysis eXpressions) est le langage qui permet de créer ses propres indicateurs : taux de marge, CAC, marge après marketing. On y règle d'abord la question qui bloque tout le monde — colonne ou mesure ? — puis on écrit les mesures réelles du modèle TheLook.
5
DAX : écrire des indicateurs qui tiennent debout

Colonne calculée vs mesure — la distinction qui débloque tout

C'est le point qui bloque tous les débutants. Les deux s'écrivent en DAX, mais ils ne font pas la même chose :

Colonne calculéeMesure
QuandAu chargement / rafraîchissementÀ l'affichage, dans chaque visuel
CommentLigne à ligne, dans la tableAgrégée selon le contexte du visuel
StockageStockée, occupe de la mémoireNon stockée, calculée à la volée
Pour quoiCatégoriser, créer un axe (dimension)Mesurer, agréger (CA, marge, CAC)
La règle simple
Une colonne se calcule ligne à ligne et se stocke — utile pour créer une catégorie (une tranche d'âge, un segment). Une mesure s'agrège dynamiquement selon le contexte du visuel — c'est ce qu'on veut pour presque tous les indicateurs. Réflexe : en cas de doute, c'est une mesure.

Un exemple de colonne calculée

Créer une tranche d'âge dans SRC_USERS pour pouvoir ensuite répartir le CA par tranche — ça, c'est un axe, donc une colonne :

// Colonne calculée dans SRC_USERS
Tranche Age =
SWITCH(
    TRUE(),
    SRC_USERS[age] < 25, "18-24",
    SRC_USERS[age] < 35, "25-34",
    SRC_USERS[age] < 50, "35-49",
    "50+"
)

La table de mesures _Mesures

Bonne pratique dès le départ : dans l'onglet Modélisation, créez une « Nouvelle table » vide nommée _Mesures. Toutes vos mesures y seront rangées, séparées des tables de données. C'est plus propre et plus facile à retrouver.

Les mesures de chiffre d'affaires et de marge

On commence par les fondations. Ces mesures agrègent les colonnes de la table de faits SRC_ORDER_ITEMS :

CA Réel  = SUM(SRC_ORDER_ITEMS[sale_price])
Coût     = SUM(SRC_ORDER_ITEMS[cost])
Marge    = SUM(SRC_ORDER_ITEMS[margin])

Une mesure peut en réutiliser une autre — c'est même vivement recommandé. Le taux de marge se construit à partir des deux précédentes :

Taux de Marge = DIVIDE([Marge], [CA Réel], 0)

DIVIDE — le réflexe anti division par zéro

Pourquoi DIVIDE et pas un simple / ? Parce qu'une division par zéro provoque une erreur qui casse le visuel. DIVIDE gère ce cas proprement :

DIVIDE( numérateur, dénominateur, [résultat_si_zéro] )

// Si le dénominateur vaut 0 (ou est vide) :
//   /       → erreur, le visuel casse
//   DIVIDE  → renvoie le 3e argument (ici 0), jamais d'erreur
Toujours DIVIDE pour un ratio
Taux de marge, CAC, ROAS, taux de conversion : tout ratio se calcule avec DIVIDE. Le troisième argument (souvent 0 ou vide) décide quoi afficher quand il n'y a pas de dénominateur. C'est un réflexe de robustesse : un canal sans dépense ne doit pas faire planter tout le tableau.

Les mesures marketing et clients

On enrichit avec les dépenses média (table SRC_MARKETING) et le nombre de clients (table SRC_USERS) :

Spend Mkt       = SUM(SRC_MARKETING[spend])
Marge après Mkt = [Marge] - [Spend Mkt]
Clients         = DISTINCTCOUNT(SRC_USERS[user_id])
CAC             = DIVIDE([Spend Mkt], [Clients], 0)

Notez DISTINCTCOUNT pour les clients : on compte des user_id uniques, pas des lignes (rappel du module 4). Et le CAC — coût d'acquisition client — est un simple DIVIDE de la dépense par le nombre de clients. Une mesure de trois lignes qui répond à une vraie question de pilotage marketing.

CALCULATE — le cœur du DAX utile

CALCULATE est la fonction la plus puissante de DAX. Elle évalue une expression en modifiant le contexte de filtre. Autrement dit : « calcule ce KPI, mais comme si tel filtre était appliqué ».

CALCULATE( expression, filtre1, filtre2, ... )

// CA du canal Search uniquement, quel que soit le visuel
CA Search = CALCULATE( [CA Réel], SRC_ORDER_ITEMS[traffic_source] = "Search" )

Cas concret et grounded sur TheLook : certaines commandes n'ont pas de canal (traffic_source vide, vu au module 3). Pour isoler ce CA non attribué, on force le contexte avec CALCULATE + ISBLANK :

CA Sans Canal = CALCULATE( [CA Réel], ISBLANK(SRC_ORDER_ITEMS[traffic_source]) )
Contexte de filtre, en une phrase
Un visuel filtre déjà vos données (une ligne « Search » d'un tableau ne montre que Search). CALCULATE permet de changer ce filtre à l'intérieur d'une mesure. C'est ce qui rend possibles les comparaisons, les « part du total », les « versus budget » — tout ce qui fait la vraie analyse.

Contexte de ligne vs contexte de filtre

Deux contextes cohabitent en DAX, et les distinguer évite la plupart des confusions :

Règle pratique : une colonne raisonne « à l'intérieur d'une ligne » ; une mesure raisonne « à l'intérieur d'un contexte de filtre ». C'est pour ça qu'une même logique s'écrit différemment selon qu'on en fait une colonne ou une mesure.

Exercice corrigé

Énoncé
Vous devez afficher le taux de marge global de TheLook dans une carte KPI. Quelle mesure écrivez-vous, et à quel ordre de grandeur devez-vous vous attendre ?
// Correction
Taux de Marge = DIVIDE([Marge], [CA Réel], 0)

Lecture attendue : sur le périmètre « Performance par canal » du modèle, la marge totale (≈ 50 196 €) rapportée au CA (≈ 102 794 €) donne un taux de marge global de l'ordre de 48,8 %. Si votre carte affiche 4 880 % ou 0,49, c'est un problème de format (pourcentage vs décimal), pas de calcul — un sanity check à faire systématiquement.

Fiche DAX — colonne vs mesure
Colonne calculée
Ligne à ligne, stockée. Pour créer un axe / une catégorie (ex : Tranche Age).
Mesure
Agrégée selon le contexte du visuel, non stockée. Pour presque tous les KPI.
En cas de doute
C'est une mesure. Une colonne ne se justifie que pour catégoriser / trier.
Table _Mesures
Ranger toutes ses mesures dans une table dédiée, propre et repérable.
Fiche DAX — DIVIDE et CALCULATE
DIVIDE — ratio propre
DIVIDE(num, dénom, 0)
Zéro danger de division par zéro. Le 3e argument = valeur si dénom nul.
CALCULATE — changer le filtre
CALCULATE([Mesure], filtre)
Évalue une mesure avec un contexte de filtre modifié.
Taux de marge
DIVIDE([Marge], [CA Réel], 0)
CAC
DIVIDE([Spend Mkt], [Clients], 0)
Clients (uniques)
DISTINCTCOUNT(SRC_USERS[user_id])
CA non attribué
CALCULATE([CA Réel], ISBLANK(SRC_ORDER_ITEMS[traffic_source]))
Suite du parcours
Nos mesures sont prêtes. Mais pour croiser proprement les ventes, les clients et le marketing, il faut relier les tables. Le module 6 pose les fondations : clés, cardinalité, schéma en étoile.

Ouvrir le module 6 — Modélisation simple