Blog Pro de Jean-Baptiste HEREN - Tag - MDX Notes d'un consultant Freelance en Informatique 2015-11-03T21:34:19+01:00 JB HEREN urn:md5:e39389b5ec134d99645112fce3d957df Dotclear Formules MDX - Associer deux dimentions temporelles avec LINKMEMBER urn:md5:6fdff6a2ce08b10b09b67c63f395ea6f 2010-09-08T22:00:00+02:00 2010-09-09T12:55:22+02:00 Jean-Baptiste Heren Décisionnel Business 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 &quot;validité des prévisions&quot;:<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 &quot;Schedule Time&quot;, on constate que l'&quot;Extract Time&quot; 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 Services urn:md5:51f8de17982d541256c6e39a29898ba5 2010-03-23T16:47:00+01:00 2010-03-24T09:34:27+01:00 Jean-Baptiste Heren Décisionnel Business IntelligenceMDXSQL Server 2005SSAS L'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 &quot;reporting&quot; 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 &quot;photo&quot; 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 &quot;la plus proche&quot; 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] &gt; 0,<br /> 1- ABS(([Measures].[QTY] - [Measures].[Qty on Schedule]) /iif([Measures].[Qty on Schedule] &gt; [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 />