Support formation Rapports Power BI

Travailler avec plusieurs tables de faits

Modéliser - Plusieurs tables de faits

Un modèle Power BI contient rarement une seule table de faits : ventes et objectifs, commandes et stocks, budget et réalisé. Ce modèle à plusieurs étoiles est appelé modèle en constellation (ou schéma en galaxie). Source

Les règles de base

  • Chaque table de faits a sa propre granularité, constante sur toutes ses lignes (ex. : une ligne par ligne de commande, une ligne par mois et par catégorie). Source
  • Les tables de faits ne sont jamais reliées entre elles : elles communiquent par les dimensions qu'elles partagent.
  • Les dimensions partagées sont appelées dimensions conformes : même clé, mêmes attributs, utilisées par toutes les étoiles (la table de dates en est l'exemple type). Source
  • Les relations restent en un-à-plusieurs, à sens unique, de la dimension vers chaque table de faits.
  • Les colonnes numériques des tables de faits sont masquées : on ne présente que des mesures.

Exemple fil rouge

TableTypeGranularité
DimDateDimension conformeJour
DimProductDimension conformeProduit (avec Catégorie)
DimStoreDimension conformeMagasin
FactSalesFaitsJour × produit × magasin
FactInventoryFaitsJour × produit × magasin (photo de stock)
FactTargetFaitsMois × catégorie

Cas 1 | Même granularité : dimensions partagées

FactSales et FactInventory ont la même granularité.

  • Relier DimDate, DimProduct et DimStore à chacune des deux tables de faits (1:*, sens unique).
  • Un segment sur DimProduct[Catégorie] filtre alors les ventes et les stocks en même temps.
  • Les axes et segments d'un visuel combinant les deux tables doivent toujours provenir des dimensions, jamais d'une table de faits.
Ventes = SUM ( FactSales[Montant] )

Stock fin de période =
CALCULATE (
    SUM ( FactInventory[Quantité] ),
    LASTDATE ( DimDate[Date] )
)

Taux de rotation = DIVIDE ( [Ventes], [Stock fin de période] )

Point de vigilance : un stock est un fait semi-additif (on ne l'additionne pas dans le temps), d'où LASTDATE ou LASTNONBLANK. Source

Cas 2 | Granularité différente : faits plus agrégés

FactTarget est stockée au mois et à la catégorie, plus haut que DimDate (jour) et DimProduct (produit).

Côté date

  • Stocker dans FactTarget le premier jour de la période (ex. 01/03/2026 pour mars 2026), en type Date.
  • Créer une relation 1:* classique entre DimDate[Date] et FactTarget[Mois]. Source

Côté produit

Trois solutions, de la plus recommandée à la plus ponctuelle :

  • Dimension Catégorie dédiée : créer DimCategory (une ligne par catégorie), reliée en 1:* à FactTarget et à DimProduct. Solution la plus lisible.
  • Relation plusieurs-à-plusieurs DimProduct[Catégorie] *:* FactTarget[Catégorie], filtrage unidirectionnel de DimProduct vers FactTarget. Source
  • Relation virtuelle avec TREATAS, sans relation physique (voir cas 3).

Contrôler l'agrégation

Sans précaution, un objectif mensuel affiché au jour ou au produit donne un résultat faux (vide ou dupliqué). La mesure doit renvoyer BLANK sous la granularité de la table :

Objectif =
IF (
    NOT ISFILTERED ( DimDate[Date] )
        && NOT ISFILTERED ( DimProduct[Produit] ),
    SUM ( FactTarget[Montant objectif] )
)

Écart à l'objectif = [Ventes] - [Objectif]
% Atteinte = DIVIDE ( [Ventes], [Objectif] )

Variante possible : répartir l'objectif au jour au prorata du nombre de jours du mois (calcul plus avancé, à réserver aux besoins avérés).

Cas 3 | Relation virtuelle avec TREATAS

TREATAS applique les valeurs d'une colonne comme filtre sur une autre colonne, sans relation dans le modèle. Utile pour un besoin ponctuel ou pour éviter une relation *:* ambiguë. Source

Objectif (TREATAS) =
CALCULATE (
    SUM ( FactTarget[Montant objectif] ),
    TREATAS ( VALUES ( DimProduct[Catégorie] ), FactTarget[Catégorie] )
)
  • Avantage : pas de relation supplémentaire, pas de risque d'ambiguïté.
  • Inconvénient : la logique doit être reprise dans chaque mesure, et une relation virtuelle est généralement moins efficace qu'une relation physique sur de gros volumes. Source

Ce qu'il faut éviter

  • Relier deux tables de faits directement (relation *:* entre FactSales et FactTarget) : résultats faux ou incompréhensibles. Microsoft recommande de passer par des dimensions communes. Source
  • Fusionner des faits de granularités différentes dans une même table.
  • Activer le filtrage bidirectionnel pour « faire fonctionner » un visuel : chemins ambigus et performances dégradées. Source
  • Utiliser une colonne d'une table de faits comme axe ou segment : elle ne filtre pas les autres tables de faits.

Mise en pratique

À partir du modèle de vente du support :

  • Importer une table d'objectifs mensuels par catégorie (Mois au 1er du mois, Catégorie, Montant objectif).
  • Créer la dimension Catégorie ou la relation *:* unidirectionnelle.
  • Écrire les mesures Objectif, Écart à l'objectif et % Atteinte.
  • Construire une matrice Année / Mois × Catégorie et vérifier qu'au jour ou au produit l'objectif est vide.
  • Refaire la mesure Objectif avec TREATAS et comparer les résultats dans l'analyseur de performances.