Blog Pro de Jean-Baptiste HEREN - Tag - MDXNotes d'un consultant Freelance en Informatique2015-11-03T21:34:19+01:00JB HERENurn:md5:e39389b5ec134d99645112fce3d957dfDotclearFormules MDX - Associer deux dimentions temporelles avec LINKMEMBERurn:md5:6fdff6a2ce08b10b09b67c63f395ea6f2010-09-08T22:00:00+02:002010-09-09T12:55:22+02:00Jean-Baptiste HerenDécisionnelBusiness IntelligenceMDXSQL Server 2005SSAS<p>Voici un exemple d'utilisation de la fonction LINKMEMBER pour le calcul
d'une mesure dans un cube Miscosoft SSAS.</p>
<h2>Présentation</h2>
Cet exemple est extrait d'un travail sur le thème de la "validité des
prévisions":<br />
<ul>
<li>Des données de prévision commerciale sont extraites et stockées chaque
semaine. Chacune de ces extractions correspond à une valeur EXTRACT_DATE.</li>
<li>Les données d'entrée nous donnent des quantités (QTY) par date de prévision
(SCHED_HIPT_DTTM)</li>
<li>Dans le cas réel, plusieurs dimensions complémentaires sont présentes
(client, produit, etc.)</li>
</ul> Notre table de faits présente donc au minimum, pour l'exemple, les éléments
suivants :<br />
<ul>
<li>EXTRACT_DATE (KEY) </li>
<li>SCHED_SHIP_DTTM ((KEY)</li>
<li>QTY (MEASURE)</li>
</ul>
<h2>Besoin d'analyse</h2>
Il s'agit d'observer au cours du temps (date de vision), l'évolution des
quantités prévues pour une date donnée (date de prévision).<br />
Par exemple, nous voulons observer l'évolution des quantités prévues pour Mai
2010, durant les mois qui précèdent. Le but est d'évaluer la fiabilité des
prévisions de M-1 à M-6.<br />
<br />
<h2>Modèle</h2>
On a donc un modèle de base contenant une table de fait et deux dimensions
temporelles.<br />
<a href="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/Cube_star_model.jpg"><img title="Cube_star_model.jpg, sept. 2010" alt="" src="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/.Cube_star_model_m.jpg" /></a><br />
<br />
<h2>Dimensions</h2>
Les dimensions que nous voulons lier ont une structure identique.<br />
<h3>Extract Time (date de Vision)</h3>
<br />
<a href="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/Extract_time_dimension.jpg"><img title="Extract_time_dimension.jpg, sept. 2010" alt="" src="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/.Extract_time_dimension_m.jpg" /></a><br />
<h3>Schedule Time (date de réalisation prévue de la mesure)</h3>
<a href="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/Sched_time_dimension.jpg"><img title="Sched_time_dimension.jpg, sept. 2010" alt="" src="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/.Sched_time_dimension_m.jpg" /></a><br />
<h2>Formule</h2>
Dans les formules suivantes, nous utilisons la fonction <a hreflang="fr" href="http://technet.microsoft.com/fr-fr/library/ms146058.aspx">LINKMEMBER</a>
(Retourne le membre équivalent à un membre spécifié dans une hiérarchie
spécifique).<br />
<pre>
CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[Qty on Schedule]</strong><br /> AS SUM(<br /><strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time])<br />,[Measures].[QTY]<strong>)</strong>, <br />VISIBLE = 1;<br /><br />CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[QTY M-1]</strong><br /> AS SUM(parallelperiod([Extract Time].[Extract Time].[Month], 1, <strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time])),[Measures].[QTY]), <br />VISIBLE = 1 ;<br /><br />CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[QTY M-2]</strong><br /> AS SUM(parallelperiod([Extract Time].[Extract Time].[Month], 2, <strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time]<strong>)</strong>),[Measures].[QTY]), <br />VISIBLE = 1; <br /><br />CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[QTY M-3]</strong><br /> AS SUM(parallelperiod([Extract Time].[Extract Time].[Month], 3, <strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time]<strong>)</strong>),[Measures].[QTY]), <br />VISIBLE = 1; <br /><br />CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[QTY M-4]</strong><br /> AS SUM(parallelperiod([Extract Time].[Extract Time].[Month], 4, <strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time]<strong>)</strong>),[Measures].[QTY]), <br />VISIBLE = 1; <br /><br />CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[QTY M-5]</strong><br /> AS SUM(parallelperiod([Extract Time].[Extract Time].[Month], 5, <strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time]<strong>)</strong>),[Measures].[QTY]), <br />VISIBLE = 1; <br /><br />CREATE MEMBER CURRENTCUBE.[MEASURES].<strong>[QTY M-6]</strong><br /> AS SUM(parallelperiod([Extract Time].[Extract Time].[Month], 6, <strong>LINKMEMBER(</strong>[Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time]<strong>)</strong>),[Measures].[QTY]), <br />VISIBLE = 1;
</pre>
<h2>Résultat</h2>
En ne précisant que la "Schedule Time", on constate que l'"Extract Time" s'est
bien positionnée automatiquement.<br />
<br />
<img title="cube_browing_test.jpg, sept. 2010" alt="" src="http://blog.jbheren.com/public/Decisionnel/linkmember_dates/.cube_browing_test_m.jpg" /><br />Analyse d'écarts dans le temps avec Analysis Servicesurn:md5:51f8de17982d541256c6e39a29898ba52010-03-23T16:47:00+01:002010-03-24T09:34:27+01:00Jean-Baptiste HerenDécisionnelBusiness IntelligenceMDXSQL Server 2005SSASL'exemple suivant illustre un cas courant d'analyse d'écarts d'une mesure dans
le temps, traité via des formules MDX dans un cube Microsoft Analysis
Services. <br />
Cela pourrait s'appliquer à un "reporting" sur la qualité des prévisions de
vente par rapport aux ventes réalisé. <h2>Présentation du cas</h2>
Une table de faits contenant une "photo" mensuelle d'un calendrier de
prévisions<br />
<br />
<pre>
|--------------------|
</pre>
<pre>
| Fact Table |
</pre>
<pre>
|--------------------|
</pre>
<pre>
|EXTRACT_DATE (key) | Date d'extraction (Photo des données)
</pre>
<pre>
|SCHEDULE_DATE (Key) | Date de la prévision
</pre>
<pre>
|Item_Code (Key) | Code article
</pre>
<pre>
|... | Divers axes (client, Filiale, etc.)
</pre>
<pre>
|QTY(measure) | Quantité prévue
</pre>
<pre>
|--------------------|
</pre>
Notre but est de contrôler a posteriori, l'évolution de la quantité prévue, au
cours du temps (chargements mensuels). L'idée est d'évaluer la fiabilité des
prévisions au cours du temps, par rapport au réalisé.<br />
Pour exemple :<br />
- On choisit d'observer l'évolution de la quantité prévue en Juin 2010<br />
- Nous souhaiterons donc afficher pour chaque date d'extraction précédent Juin
2010, la quantité enregistrée sur Juin 2010<br />
- Cela revient à comparer Juin 2010 respectivement avec chacune des périodes
d'extraction désirées.<br />
<br />
Dans ce contexte, il est intéressant de savoir détecter l'équivalence entre les
éléments de nos deux dimensions temporelles.<br />
<a href="http://blog.jbheren.com/public/Decisionnel/linkmember/Test_cube_with_two_time_hierarchies.jpg"><img title="Test_cube_with_two_time_hierarchies.jpg, mar. 2010" alt="" src="http://blog.jbheren.com/public/Decisionnel/linkmember/.Test_cube_with_two_time_hierarchies_t.jpg" /></a><br />
Cela peut être réalisé par l'utilisation de la fonction MDX suivante, qui
retourne le membre équivalent à un membre spécifié dans une hiérarchie
spécifique :<br />
<pre>
<a href="http://msdn.microsoft.com/fr-fr/library/ms146058.aspx">LinkMember</a>(Member_Expression, Hierarchy_Expression)
</pre>
L'utilisation de cette fonction est illustrée dans les formules
suivantes.<br />
<br />
<h2>Les Formules</h2>
Voici maintenant les formules utilisées pour calculer les écarts pour chaque
période par rapport à la période de référence.<br />
<br />
<strong>[Qty on Schedule]</strong><br />
Description : Quantité de référence. correspond à la date d'extraction "la plus
proche" de la date prévue.<br />
<pre>
SUM(LINKMEMBER([Schedule Time].[Schedule Time].currentmember,[Extract Time].[Extract Time])
</pre>
<br />
<strong>[Accuracy Qty]</strong><br />
description : % de validité des quantités (totales) entre la date d'extraction
du contexte et la quantité de référence (ci-dessus)<br />
<pre>
iif([Measures].[QTY] > 0,<br />
1- ABS(([Measures].[QTY] - [Measures].[Qty on Schedule]) /iif([Measures].[Qty on Schedule] > [Measures].[QTY],[Measures].[Qty on Schedule],[Measures].[QTY]))<br />
,0)
</pre>
<br />
<strong>[Accuracy Qty by Item]</strong><br />
Description : % de validité pondéré par article<br />
<pre>
SUM(descendants([Item].[By Model].currentmember,[Item].[By Model].[Item Code])<br />
,Measures.[Accuracy Qty]*Measures.[Qty on Schedule])/SUM(Measures.[Qty on Schedule])
</pre>
<br />
<h2>Exemple de rapport</h2>
Voici un exemple de rapport attaquant un cube SSAS depuis Cognos.<br />
<a href="http://blog.jbheren.com/public/Decisionnel/linkmember/Cognos_report_example.jpg"><img title="Cognos_report_example.jpg, mar. 2010" alt="" src="http://blog.jbheren.com/public/Decisionnel/linkmember/.Cognos_report_example_t.jpg" /></a><br />