Navigation au sein d’un Cube OLAP

Un des principaux points de la Business Intelligence est l’analyse multidimensionnelle. Il devient primordial de pouvoir étudier une même information suivant différents axes. Par exemple, il est très intéressant pour une entreprise de pouvoir interpréter son chiffre d’affaires par zone géographique, par période temporelle, par produit, par client…

Un moyen pour effectuer ces analyses est d’utiliser des cubes (ou hyper cube). Un cube permet de stocker une information et de la lier à plusieurs dimensions afin d’effectuer des analyses en fonction de celles-ci. Je vous propose dans ce post de nous intéresser à différentes façons de naviguer au sein d’un cube afin de récupérer une information.

Il existe un certain nombre d’outils graphiques, souvent spécifiques aux éditeurs du cube, qui offrent la possibilité de naviguer facilement au sein de celui-ci. Dans ce post, je ne vais parler que de l’outil appelé JPivot qui permet de naviguer au sein d’un cube Mondrian.

Il existe aussi un langage spécifique à la navigation multidimensionnelle : le langage MDX. Ce langage peut être comparé au SQL pour les bases relationnelles. Je vous propose donc de présenter ensuite quelques bases du MDX.

JPivot

JPivot est un moyen simple pour un utilisateur non informaticien d’obtenir une information à partir d’un cube, il permet de transcrire des actions graphiques en requête MDX.

L’outil JPivot présente le cube sous forme de tableau croisé. Il permet d’insérer en abscisse ou en ordonné les différentes dimensions afin d’étudier les mesures du cube.

Regardons pour commencer une petite vidéo pour ressortir le Chiffre d’affaires par Produit et par marché sur différentes années : https://www.sodifrance.fr/blog/public/images/BI/video/JPivot_skin.swf

Comme vous pouvez le voir, rien de plus simple pour obtenir l’information que l’on souhaite. On peut grâce à cet outil accéder à toutes les informations contenues dans le cube.
Cependant, cet outil qui a été développé dans le but de rester simple et facile d’utilisation ne permet pas de profiter de toutes les possibilités qu’offre le langage MDX. Il est donc intéressant d’avoir quelques bases sur ce langage afin de répondre à des besoins parfois plus spécifiques.

Les bases du MDX

Je vous propose de décortiquer la requête qui a été générée par JPivot dans la vidéo. Pour faciliter l’explication, cette requête a été un peu simplifiée.

SELECT 
	Crossjoin([Time].[All Years].Children,{[Measures].[Quantity]})
	ON COLUMNS,
	Crossjoin([Markets].[All Markets].Children, [Product].[All Products].Children)
	ON ROWS
FROM [SteelWheelsSales]

Résultat :
Tableau analyse 1

Pour ceux qui connaissent le SQL, je pense que vous ne serez pas perdus. En effet, il y a beaucoup de ressemblances, vous verrez cependant que ce langage offre des nouvelles possibilités grâce à certaines fonctions très intéressantes que je détaillerai un peu plus bas.

La requête est séparée en plusieurs parties : SELECT, FROM, WHERE.

SELECT

La principale différence avec le SQL vient justement du SELECT qui demande des informations sur les champs à mettre en colonne et des informations sur les champs à mettre en ligne. C’est ce qui est interprété avec les tags ON COLUMNS et ON ROWS.

Nous avons donc
Crossjoin([Time].[All Years].Children,{[Measures].[Quantity]})
en colonne et
Crossjoin([Markets].[All Markets].Children, [Product].[All Products].Children)
en ligne.

La fonction Crossjoin() permet de croiser les données sur les axes et donc d’avoir cet aspect d’arborescence dans le tableau. Nous voyons pour les lignes que nous croisons les Marchés avec les Produits, et pour les colonnes nous croisons le Temps avec la mesure Quantité.

Attention cependant, il est interdit de mettre des champs d’une même dimension en ligne et en colonne. Par exemple, il n’est pas possible d’indiquer

SELECT
	[Time].[All Years].Children ON COLUMS,
	[Time].[All Years].[Months].Children ON ROWS
FROM ...

Pourquoi ? Tout simplement parce que ceci n’a aucun sens. Une information n’est liée qu’une seule fois à une dimension.

FROM

Le champ FROM permet simplement d’indiquer le cube que nous souhaitons utiliser, au même titre que les tables en SQL.

WHERE

Le champ WHERE, qui n’est pas présent dans cet exemple de requête, permet d’indiquer des conditions sur les dimensions non présentes dans le champ SELECT.

Quelques fonctions utiles en MDX

La fonction Children

Vous avez sans doute remarqué que les dimensions dans la requête se terminent par .Children. Cette fonction retourne les enfants d’un membre d’une hiérarchie.

Dans notre cas la hiérarchie « Time » était de cette forme :

Time
|
`-- All Years
	|
	`-- 2003
		|
		`-- Janvier
		|
		`-- Février
		|
		`-- …
	|
	`-- 2004
		|
		`-- Janvier
		|
		`-- Février
		|
		`-- …
	|
	`-- 2005

[Time].[All Years].Children retroune donc 2003, 2004, 2005 alors que [Time].[All Years].[2003].Children aurait retourné Janvier, Février, Mars, …

Le mot clé NON EMPTY

Il arrive parfois que des membres d’une hiérarchie ne contiennent pas de valeur. Le mot clé NON EMPTY permet d’éliminer les cellules qui sont vides.
Si, par exemple, il n’y avait pas eu de vente en 2004, la requête ci-dessous n’aurait pas affiché la colonne 2004.

SELECT 
	NON EMPTY Crossjoin([Time].[All Years].Children,{[Measures].[Quantity]})
	ON COLUMNS,
	Crossjoin([Markets].[All Markets].Children, [Product].[All Products].Children)
	ON ROWS
FROM [SteelWheelsSales]

La fonction Order()

La fonction Order() permet, comme son nom l’indique, de classer les éléments en sortie. Cette fonction attend au moins 2 paramètres :

  • Les membres à classer
  • La mesure qu’il faut prendre en compte pour les classer
  • (Facultatif) le mot clef DESC, si l’on souhaite les classer par ordre décroissant.

La requête ci-dessous aurait classé les lignes par marché en fonction de la quantité vendue dans l’ordre croissant :

SELECT
	Crossjoin([Time].[All Years].Children, {[Measures].[Quantity]}) ON COLUMNS,
	Crossjoin(
		Order([Markets].[All Markets].Children, [Measures].[Quantity]), [Product].[All Products].Children
	) ON ROWS
FROM [SteelWheelsSales]

La fonction Topcount()

La fonction Topcount() est une amélioration de la fonction Order(). Cette fonction trie un jeu en ordre décroissant et retourne le nombre spécifié d'éléments avec les valeurs les plus élevées.

La requête ci-dessous permet de ne sélectionner en ligne que les 2 produits avec la plus grande quantité vendue par marché.

SELECT
	Crossjoin([Time].[All Years].Children, {[Measures].[Quantity]}) ON COLUMNS,
  	
	Crossjoin(
		[Markets].[All Markets].Children,
		Topcount([Product].[All Products].Children, 2.0, [Measures].[Quantity])
	) ON ROWS
FROM [SteelWheelsSales]

Tableau analyse 2

Le langage MDX offre encore bien d’autres fonctionnalités que je n’ai pas présentées ici. Si vous souhaitez en connaître d’avantage, je vous conseille d’aller voir la documentation de msdn qui est très complète : http://msdn.microsoft.com/fr-fr/library/ms145506.aspx.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.