<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ixto-Blog &#187; MDX im SQL Server 2005</title>
	<atom:link href="http://www.ixto.de/blog/category/sql-server-2005/mdx-2005/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ixto.de/blog</link>
	<description>Business Intelligence, Database Consulting, Software Development</description>
	<lastBuildDate>Mon, 26 Sep 2011 09:23:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MDX ParallelPeriod – bleib auf Deinem Level (Andere gibt’s vielleicht nicht)</title>
		<link>http://www.ixto.de/blog/sql-server-2005/mdx-parallelperiod-%e2%80%93-bleib-auf-deinem-level-andere-gibt%e2%80%99s-vielleicht-nicht/</link>
		<comments>http://www.ixto.de/blog/sql-server-2005/mdx-parallelperiod-%e2%80%93-bleib-auf-deinem-level-andere-gibt%e2%80%99s-vielleicht-nicht/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 14:05:31 +0000</pubDate>
		<dc:creator>Marcel Ebner</dc:creator>
				<category><![CDATA[MDX im SQL Server 2005]]></category>
		<category><![CDATA[MDX im SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://www.ixto.de/blog/allgemein/mdx-parallelperiod-%e2%80%93-bleib-auf-deinem-level-andere-gibt%e2%80%99s-vielleicht-nicht/</guid>
		<description><![CDATA[Um innerhalb einer Zeitdimension zurückliegende Member zu erreichen braucht es kein Voodoo, MDX stellt eine bequeme Funktion namens &#8220;PARALLELPERIOD&#8221; zur Verfügung, welche zu einem angegebenen Element (Bsp. August 2003) über eine Ebene der Zeitdimension (Monat, Quartal, Jahr …) eine bestimmte Anzahl von Schritten (12 Monate, 2 Jahre o. ä.) zurück oder vorwärts geht.


Zum Beispiel folgende [...]]]></description>
			<content:encoded><![CDATA[<p>Um innerhalb einer Zeitdimension zurückliegende Member zu erreichen braucht es kein Voodoo, MDX stellt eine bequeme Funktion namens &#8220;PARALLELPERIOD&#8221; zur Verfügung, welche zu einem angegebenen Element (Bsp. August 2003) über eine Ebene der Zeitdimension (Monat, Quartal, Jahr …) eine bestimmte Anzahl von Schritten (12 Monate, 2 Jahre o. ä.) zurück oder vorwärts geht.</p>
<p><span id="more-71"></span><br />
<br\><br />
Zum Beispiel folgende Abfrage:</p>
<p style="margin-left: 35pt;"><span style="color: blue; font-family: Courier New; font-size: 10pt;">WITH</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;">MEMBER</span> LevelMonth_OneYearAgo <span style="color: blue;">AS</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: maroon;">PARALLELPERIOD</span>([Date].[Calendar].[Month],12,</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].<span style="color: maroon;">CURRENTMEMBER</span>).<span style="color: blue;">MEMBER_CAPTION</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;">MEMBER</span> LevelYear_OneYearAgo <span style="color: blue;">AS</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: maroon;">PARALLELPERIOD</span>([Date].[Calendar].[Calendar Year],1,</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].<span style="color: maroon;">CURRENTMEMBER</span>).<span style="color: blue;">MEMBER_CAPTION</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;">SELECT</span> {</span><br />
<span style="font-family: Courier New; font-size: 10pt;">LevelMonth_OneYearAgo</span><br />
<span style="font-family: Courier New; font-size: 10pt;">,LevelYear_OneYearAgo</span><br />
<span style="font-family: Courier New; font-size: 10pt;">} <span style="color: blue;">ON</span> 0 ,</span><br />
<span style="font-family: Courier New; font-size: 10pt;">{</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].[Month].&amp;[2003]&amp;[8]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">}<span style="color: blue;">ON</span> 1 <span style="color: blue;">FROM</span> [Adventure Works]</span></p>
<p>liefert zurück:</p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/101209_0001_Parallel1.png" alt="" /><br />
<br\><br />
Obwohl das Hierarchielevel &#8220;[Date].[Calendar].[Calendar Year]&#8221; auf keiner Achse angegeben ist, kann es durch seine bestehende Attributrelation zur Ebene &#8220;[Date].[Calendar].[Month]&#8221; angesprochen werden .<br />
<br\><br />
Sind also Attributbeziehungen innerhalb der verschiedenen Zeitebenen definiert, können auch andere als in der Abfrage verwendete Ebenen der Zeitdimension mit PARALLELPERIOD verwendet werden.<br />
<br\><br />
Was aber passiert, wenn es im angegebenen zurückliegenden Zeitraum keinen Member gibt? Im AdventureWorks Cube 2008 ist der erste Member der Zeitdimension der erste Juli 2001. Ersetzt man den oben abgefragten Monat auf der Achse mit &#8220;[Date].[Calendar].[Month].&amp;[2002]&amp;[6]&#8221; liefert die Abfrage folgendes zurück:</p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/101209_0001_Parallel2.png" alt="" /><br />
<br\><br />
Das Ergebnis für PARALLELPERIOD mit Level &#8220;Month&#8221; ist korrekt, aber was ist mit dem Ergebnis für Level &#8220;Year&#8221; los? Angezeigt wird der Dezember 2001, der nun definitiv kein Jahr hinter dem Juni 2002 liegt. In diesem Fall wird nun der letzte Monat des Vorjahres angezeigt, also das letzte Member der darunterliegenden Ebene. Auch darauf sollte man sich nun nicht verlassen, beachten Sie das folgende Beispiel (und, wenn möglich, führen Sie das Statement auch mal auf Ihrem eigenen Adventure Works Cube aus)<br />
<br\><br />
Ziel der Abfrage ist den allseits beliebten &#8220;Sales Amount&#8221; der Monate 2001 bis Ende 2002 zu ermitteln. Beim Cubebrowsen stellt sich folgendes heraus:</p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/101209_0001_Parallel3.png" alt="" /><br />
<br\><br />
Zwischen Januar 2001 und Juni 2001 sind keine Werte für &#8220;Sales Amount&#8221; vorhanden, eine ähnliche MDX-Abfrage wie folgende:</p>
<p style="margin-left: 35pt;"><span style="color: blue; font-family: Courier New; font-size: 10pt;">WITH</span><br />
<span style="color: green; font-family: Courier New; font-size: 10pt;">//LAG: </span><br />
<span style="color: green; font-family: Courier New; font-size: 10pt;">Gibt das Element zurück, das eine angegebene Anzahl von Positionen (hier 12) vor einem angegebenen Element entlang der Dimension des Elements liegt.</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;">MEMBER</span> [Measures].[Lag_Month] <span style="color: blue;">AS</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;">([Measures].[Sales Amount],</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].<span style="color: maroon;">CURRENTMEMBER</span>.<span style="color: blue;">LAG</span>(12))</span><br />
<span style="color: green; font-family: Courier New; font-size: 10pt;"><br />
//PARALLELPERIOD: Gibt ein Element aus einer früheren Periode in derselben relativen Position wie ein angegebenes Element zurück</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;">MEMBER</span> [Measures].[PP_LevelMonth] <span style="color: blue;">AS</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;">([Measures].[Sales Amount],</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: maroon;">PARALLELPERIOD</span>([Date].[Calendar].[Month],12,</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].<span style="color: maroon;">CURRENTMEMBER</span>))</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;"><br />
MEMBER</span> [Measures].[PP_LevelYear] <span style="color: blue;">AS</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;">([Measures].[Sales Amount],</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: maroon;">PARALLELPERIOD</span>([Date].[Calendar].[Calendar Year],1,</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].<span style="color: maroon;">CURRENTMEMBER</span>))</span><br />
<span style="font-family: Courier New; font-size: 10pt;"><span style="color: blue;"><br />
SELECT</span> {</span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Measures].[Sales Amount]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">,[Measures].[Lag_Month]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">,[Measures].[PP_LevelMonth]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">,[Measures].[PP_LevelYear]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">} <span style="color: blue;">ON</span> 0,</span><br />
<span style="font-family: Courier New; font-size: 10pt;">{ <span style="color: green;">//Level month on axis 1</span></span><br />
<span style="font-family: Courier New; font-size: 10pt;">[Date].[Calendar].[Month].&amp;[2001]&amp;[7]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">    : [Date].[Calendar].[Month].&amp;[2002]&amp;[12]</span><br />
<span style="font-family: Courier New; font-size: 10pt;">} <span style="color: blue;">ON</span> 1 <span style="color: blue;">FROM</span> [Adventure Works]</span></p>
<p>ergibt:</p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/101209_0001_Parallel4.png" alt="" /><br />
<br\><br />
Die &#8220;Sales Amount&#8221; Werte für das mit PARALLELPERIOD Level &#8220;Year&#8221; erstellte Member sind in Unordnung geraten. Schon ab Januar 2002 werden die rückliegenden Werte angezeigt, obwohl erst der Juli 2002 Werte für das aktuelle und das zurückliegende Jahr aufweist.<br />
<br\><br />
Die Werte der Member welche mit der MDX Funktion &#8220;Lag&#8221; oder mit dem in der Achse verwendeten Level, nämlich &#8220;Month&#8221; erstellt wurden sind korrekt.</p>
<p>Deshalb, &#8220;Schuster &#8211; bleib bei Deinem Leisten&#8221; und bei PARALLELPERIOD im abgefragten Level.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ixto.de/blog/sql-server-2005/mdx-parallelperiod-%e2%80%93-bleib-auf-deinem-level-andere-gibt%e2%80%99s-vielleicht-nicht/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problem mit Excel 2007 und Analysis Services KPIs</title>
		<link>http://www.ixto.de/blog/sql-server-2008/problem-mit-excel-2007-und-analysis-services-kpis/</link>
		<comments>http://www.ixto.de/blog/sql-server-2008/problem-mit-excel-2007-und-analysis-services-kpis/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 09:33:09 +0000</pubDate>
		<dc:creator>Markus Raatz</dc:creator>
				<category><![CDATA[MDX im SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>

		<guid isPermaLink="false">http://www.ixto.de/blog/allgemein/problem-mit-excel-2007-und-analysis-services-kpis/</guid>
		<description><![CDATA[Das Einbinden und Anzeigen von Analysis Services KPIs in Excel 2007 ist ja eine faszinierende und oft beworbene Möglichkeit. Leider zeigt sich in der Praxis oft, dass KPIs wirklich noch einmal speziell für Excel 2007 geprüft werden müssen, weil Berechnungen und Formatierungen in dem MDX, das Excel bei Abfragen generiert, oftmals nicht funktionieren. Dasselbe gilt [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: Arial; font-size: 10pt;">Das Einbinden und Anzeigen von Analysis Services KPIs in Excel 2007 ist ja eine faszinierende und oft beworbene Möglichkeit. Leider zeigt sich in der Praxis oft, dass KPIs wirklich noch einmal speziell für Excel 2007 geprüft werden müssen, weil Berechnungen und Formatierungen in dem MDX, das Excel bei Abfragen generiert, oftmals nicht funktionieren. Dasselbe gilt leider auch für KPIs, die in einer SharePoint-KPI-Liste verwendet werden sollen. Unlängst ist uns aber ein besonders gemeiner Fall begegnet: beim Öffnen einer Excel-Tabelle mit enthaltener Cube-Abfrage erschien immer dieser Fehler:<br />
</span></p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/071509_0933_ProblemmitE1.jpg" alt="" /><span style="font-family: Arial; font-size: 10pt;"><br />
</span><br />
<br\><br />
 <span id="more-60"></span><br />
<br\><br />
<span style="color: black; font-family: Arial; font-size: 10pt;">Der Grund war ein auf dem Cube definierter KPI mit einer Gewichtung:<br />
</span></p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/071509_0933_ProblemmitE2.jpg" alt="" /><span style="color: black; font-family: Arial; font-size: 10pt;"><br />
</span><br />
<br\><br />
<span style="color: black; font-family: Arial; font-size: 10pt;">Nachdem die Gewichtung entfernt wurde, ließen sich die Excel-Tabellen wieder normal öffnen. Vielen Dank an Horst Haschke von Hiestand und Suhr für das Übermitteln der Lösung!<br />
</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ixto.de/blog/sql-server-2008/problem-mit-excel-2007-und-analysis-services-kpis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OLAP-Datenquellen webbasiert abfragen mit  Dundas OLAP-Browser</title>
		<link>http://www.ixto.de/blog/allgemein/olap-datenquellen-webbasiert-abfragen-mit-dundas-olap-browser/</link>
		<comments>http://www.ixto.de/blog/allgemein/olap-datenquellen-webbasiert-abfragen-mit-dundas-olap-browser/#comments</comments>
		<pubDate>Mon, 13 Apr 2009 15:47:57 +0000</pubDate>
		<dc:creator>Martin Ihrke</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[MDX im SQL Server 2005]]></category>
		<category><![CDATA[MDX im SQL Server 2008]]></category>
		<category><![CDATA[Dundas]]></category>
		<category><![CDATA[Olap]]></category>

		<guid isPermaLink="false">http://www.ixto.de/blog/allgemein/olap-datenquellen-webbasiert-abfragen-mit-dundas-olap-browser/</guid>
		<description><![CDATA[Zahreiche ixto-Kunden wünschen sich, und damit sind sie wahrscheinlich nicht alleine, denn ihr Wunsch ist verständlich, eine Möglichkeit, OLAP-Datenquellen Web-basiert abzufragen. Die Vorteile liegen auf der Hand: das Vermeiden einer lokalen Softwareinstallation und deren Pflege sowie der damit verbunden Flexibilität. Der Markt an solchen Tools ist recht überschaubar und es findet sich sogar ein alter [...]]]></description>
			<content:encoded><![CDATA[<p>Zahreiche ixto-Kunden wünschen sich, und damit sind sie wahrscheinlich nicht alleine, denn ihr Wunsch ist verständlich, eine Möglichkeit, OLAP-Datenquellen Web-basiert abzufragen. Die Vorteile liegen auf der Hand: das Vermeiden einer lokalen Softwareinstallation und deren Pflege sowie der damit verbunden Flexibilität. Der Markt an solchen Tools ist recht überschaubar und es findet sich sogar ein alter Bekannter in der Schar der Anbietern: Dundas Data Visualization. Bekannt vor allem durch seine Chart-Elemente für Reporting Services, die bekanntlich seit SQL Server 2008 auch in diesem integriert sind, liefert Dundas ebenfalls einen OLAP-Client für Web-basierte Anwendungen. Die Funktionalität und Tauglichkeit des solchen soll an dieser Stelle vorgestellt werden.<br />
<span id="more-54"></span><br />
<br\><br />
Zunächst ist zu bemerken, dass der Dundas Olap-Browser als Version für Windows Forms als auch für ASP.Net verfügbar ist. Da eingangs die Rede eines reinen Webclients ist, ist die Entscheidung leicht zu treffen und fällt selbstverständlich auf ASP.Net. Wie bei Dundas üblich, gibt es eine Testversion, die weder in Funktionalität noch in zeitlicher Lauffähigkeit beschränkt ist, sondern nur ein Wasserzeichen in sämtlichen Grafiken trägt, um als Demo aufzufallen. Die ist nach einer Registrierung bei Dundas schnell installiert und bringt auch gleich zahlreiche Beispiel-Anwendungen mit, die die Funktionalitäten hinreichend demonstrieren. Sie sind sind sofort einsatzbereit, da ein Offline-Cube ebenfalls zum Lieferumfang gehört, falls keine OLAP-Datenquelle zur Verfügung steht. Eigene Analysis-Services Datenbanken sind aber auch schnell angebunden, so dass wir unverzüglich in unseren Cubes browsen können.<br />
<br\><br />
Dem Entwickler stehen dazu zwei Wege offen:</p>
<ul>
<li>Zum einen gibt es eine fertige Olap-Browser Komponte in der VisualStudio Toolbox, der direkt in eine ASP.NET-Seite eingefügt werden kann und auf den Namen <em>OlapClient</em> hört. Er enthält bereits alle wesentlichen Funktionen, so dass der Aufwand für Anpassungen des Layouts und der Funktionalität gegen null geht.</li>
<li>Darüber hinaus sind die einzelnen Bestandteile als Einzelkomponenten verfügbar, die sich frei positionieren und kombinieren lassen. Diese sind im Detail:
<ul>
<li>- OlapChart,</li>
<li>- OlapGrid,</li>
<li>- CubeSelector,</li>
<li>- CubeDimensionBrowser</li>
</ul>
<p>und einige mehr. Bindeglied der einzelnen Komponenten ist das OlapManager-Element. Über dieses wird definiert, dass die Komponenten auf die gleichen Daten zugreifen, Kennzahlen und Dimensionen verknüpft werden und Filter korrekt wirken.</li>
</ul>
<p> <img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/033009_1546_OLAPDatenqu1.jpg" border="0" alt="" width="176" height="301" align="textTop" /><br />
<br\><br />
Der OLAP-Browser organisiert sich in sogenannten Reports, die beliebig angelegt und verändert werden können. Einmal definierte Abfragen auf die Cubes bleiben damit verfüg- und veränderbar.<br />
<br\><br />
Visualisieren lassen sich die Daten innerhalb von Grafiken (Charts) und Pivottabellen (Grids). Dazu stehen die üblichen gestalterischen Möglichkeiten der Farb- und Formenwahl zur Verfügung. Drilldown, Drillthrough und weitere Cube-Operationen sind ebenfalls genauso verfügbar wie Tabellen-Operationen wie das Transponieren.</p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/033009_1546_OLAPDatenqu2.jpg" border="0" alt="" width="481" height="345" /><br />
<br\><br />
Ein Highlight ist ohne Zweifel die Web2.0-Funktionalität basierend auf dem Duo JavaScript und XML. Measures, Dimensionen und Filter lassen sich durch Drag&amp;Drop wie bei einer lokalen Anwendung definieren, wobei sich das Look&amp;Feel an den einschlägigen OLAP-Werkzeugen, wie dem SQL Server Management Studio orientiert.<br />
<br\><br />
Etwas hakelig, wenn auch trotzdem möglich, ist der Export nach Microsoft Excel. Es handelt sich hier um ein oft durch Kunden angefragtes Feature, leider ist es trotzdem keine integrierte Funktion des OLAP-Browsers. Jedoch liefern die Beispieldateien hier genügend Informationen in Form von Beispiel-Code, um den Export auch in eigene Anwendungen einzubauen.</p>
<p><img src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/033009_1546_OLAPDatenqu3.jpg" border="0" alt="" width="591" height="410" /><br />
<br\><br />
Am Ende bleibt trotz dieser kleinen Einschränkung ein sehr positiver Eindruck eines stabilen und einfach zu handhabenden Werkzeugs, OLAP-Quellen auch ohne lokal installierte Software abzufragen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ixto.de/blog/allgemein/olap-datenquellen-webbasiert-abfragen-mit-dundas-olap-browser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Korrekte MDX-Berechnungen mit den Analysis Services trotz Multiselect</title>
		<link>http://www.ixto.de/blog/sql-server-2005/mdx-2005/korrekte-mdx-berechnungen-mit-den-analysis-services-trotz-multiselect/</link>
		<comments>http://www.ixto.de/blog/sql-server-2005/mdx-2005/korrekte-mdx-berechnungen-mit-den-analysis-services-trotz-multiselect/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 09:08:36 +0000</pubDate>
		<dc:creator>Markus Schechner</dc:creator>
				<category><![CDATA[MDX im SQL Server 2005]]></category>

		<guid isPermaLink="false">http://www.ixto.de/blog/sql-server-2005/mdx/korrekte-mdx-berechnungen-mit-den-analysis-services-trotz-multiselect/</guid>
		<description><![CDATA[Seit mehreren Jahren wird immer wieder über die Problematik von berechneten Elementen in den Analysis Services in Verbindung mit Multiselects diskutiert.

So schrieb Mosha bereits 2005 in Writing multiselect friendly MDX calculations über die Probleme, die auftreten wenn eine Berechnung ein CURRENTMEMBER benötigt und Sets in der WHERE Clause verwendet werden.

Das Thema ist aber leider immer [...]]]></description>
			<content:encoded><![CDATA[<p>Seit mehreren Jahren wird immer wieder über die Problematik von berechneten Elementen in den Analysis Services in Verbindung mit Multiselects diskutiert.<br />
<br\><br />
So schrieb Mosha bereits 2005 in <a href="http://sqlblog.com/blogs/mosha/archive/2005/11/18/writing-multiselect-friendly-mdx-calculations.aspx" target="_blank">Writing multiselect friendly MDX calculations</a> über die Probleme, die auftreten wenn eine Berechnung ein CURRENTMEMBER benötigt und Sets in der WHERE Clause verwendet werden.<br />
<br\><br />
Das Thema ist aber leider immer noch aktuell und wurde durch Excel 2007 und dessen Vorliebe für Subselects beim Auswählen mehrerer Elemente der gleichen Hierarchie eher noch verschlimmert. Denn dann geben die Analysis Services unter Umständen keinen Fehler mehr zurück, sondern zeigen einfach falsche Werte an.</p>
<p> <span id="more-46"></span><br />
<br\><br />
Da die Hoffnung „Mit Katmai wird alles besser“ für diese Problematik auch nicht zutrifft, wird im Folgenden noch mal auf die Problematik eingegangen und anschließend mit Hilfe von SCOPE eine mögliche Lösung erklärt. Die Beispiele basieren wie immer auf dem Adventure Works Cube, den es bei <a href="http://www.codeplex.com/MSFTDBProdSamples" target="_blank">Codeplex</a> zum Download gibt.<br />
<br\><br />
<strong><span style="text-decoration: underline;">Das Problem</span></strong><br />
<br\><br />
Um das eigentliche Problem zu verstehen, benötigen wir zwei berechnete Elemente. Zum einen werden wir uns „Ratio to Parent Product“ anschauen, das bereits in der Adventure Works enthalten ist und folgende Definition hat:</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">Create</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> <span style="color: blue;">Member</span> <span style="color: blue;">CurrentCube</span>.[Measures].[Ratio to Parent Product] </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> </span> </p>
<div><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;"> </span><span style="color: blue;">As</span> <span style="color: blue;">Case </span></span></div>
<p><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> </p>
<p></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> </span> </p>
<p><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">        </span><span style="color: blue;">When</span> [Product].[Product Model Categories].<span style="color: maroon;">CurrentMember</span>.<span style="color: blue;">Level</span>.<span style="color: maroon;">Ordinal</span> </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">             </span>= 0 </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">        </span><span style="color: blue;">Then</span> 1 </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> </span> </p>
<p><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">        </span><span style="color: blue;">Else</span> [Measures].[Sales Amount] </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">             </span>/ </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">             </span>( [Product].[Product Model Categories].<span style="color: maroon;">CurrentMember</span>.<span style="color: maroon;">Parent</span>, </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">               </span>[Measures].[Sales Amount] ) </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> </span> </p>
<p><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">End</span>, </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;;">Format_String</span><span style="font-size: 10pt; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;;"> = <span style="color: #a31515;">&#8220;Percent&#8221;</span> ;</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;;"> </span></p>
<p>Zusätzlich definieren wir uns ein einfaches eigenes Measure, dass die Anzahl der Produkte für die jeweilige Auswahl anzeigt:</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">Create</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> <span style="color: blue;">MEMBER</span> <span style="color: blue;">CurrentCube</span>.[Measures].[Number of Products] </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">AS </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">COUNT</span>(<span style="color: blue;">EXISTING</span>([Product].[Product].[Product].<span style="color: blue;">MEMBERS</span>)); </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> </span></p>
<p><br\><br />
EXISTING sorgt dabei dafür, dass nicht immer die gleiche Anzahl zurückgegeben wird, sondern das Measure für die jeweils ausgewählten Koordinaten des Cubes neu berechnet wird.<br />
<br\><br />
Nun können wir uns das ganze in Excel ansehen. Wenn wir die beiden berechneten Measures und zusätzlich noch den Sales Amount auswählen und die „Product Categories“ auf den Zeilen ausgeben, dann ergibt sich folgendes Bild:</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image002.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image002_thumb.jpg" border="0" alt="clip_image002" width="519" height="145" /></a><br />
<br\><br />
Wie zu erwarten war, werden sowohl Number of Products, als auch die Ratio to Parent richtig für die einzelnen Produktkategorien angezeigt. Dass die Summe der Einzelwerte der „Number of Products“ nicht dem Gesamtergebnis entspricht, liegt übrigens daran, dass 209 Produkte dem, unglücklicherweise unsichtbaren, UnknownMember zugeschlagen wurden.<br />
<br\><br />
Wenn wir nun die Produktkategorien von den Zeilen in den Filter verschieben und dort mehrere Elemente auswählen,</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image004.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image004_thumb.jpg" border="0" alt="clip_image004" width="211" height="251" /></a></p>
<p>dann nutzt Excel im Hintergrund ein SUBSELECT, um diese Einschränkung abzubilden. Das Ergebnis sieht dann folgendermaßen aus:</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image006.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image006_thumb.jpg" border="0" alt="clip_image006" width="390" height="106" /></a></p>
<p>Für den Sales Amount wird korrekt die Summe der Kategorien „Accessoires“ und „Bikes“ angezeigt, was beweist, dass Excel mit seinem MDX nicht völlig daneben liegen kann. Trotzdem stimmen die Zahlen der anderen beiden Measures nicht. Es sieht aus, als wäre gar keine Einschränkung gemacht worden. Würde man sich ein Measure definieren, das <span style="font-size: 10pt; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: de; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;">[Product].[Product Model Categories].<span style="color: maroon;">CurrentMember</span>.Name</span> ausgibt, dann könnte man sehen, dass genau das geschehen ist. Innerhalb der MDX-Scripts, gibt es nur eine gewählte Produktkategorie, nämlich „[All]“. Unsere berechneten Elemente bekommen von der Tatsache, dass sie in einem beschränkten Subcube laufen, nichts mit.<br />
<br\><br />
<strong><span style="text-decoration: underline;">Die Lösung?</span></strong><br />
<br\><br />
Die Grundidee, um dieses Problem zu umgehen, ist echte Measures anzulegen und diese dann per SCOPE so zu überschreiben, dass die eigentlichen Werte dann wieder per MDX ermittelt werden.<br />
<br\><br />
Beginnen wir also mit dem Anlegen eines „echten“ Measures für die Anzahl der Produkte. Da es diesen Wert auf Faktenebene nicht gibt, müssen wir uns also erst mal eine Spalte erzeugen, die wir später als Quelle für unser neues Measure nutzen können. Wir erzeugen uns also in der Data Source View für die FactSalesSummary eine leere Dummy-Spalte.</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image008.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image008_thumb.jpg" border="0" alt="clip_image008" width="414" height="397" /></a><br />
<br\><br />
Dazu überarbeiten wir die Abfrage, die hinter der Faktentabelle liegt so, dass in beiden Teilen des UNIONS die neue Spalte „Dummy“ auftaucht.</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">SELECT</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">     </span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-tab-count: 1;">      </span>&#8230; </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-tab-count: 1;">      </span><span style="color: gray;">,</span> <span style="color: gray;">NULL</span> <span style="color: blue;">AS</span> [Dummy] </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">FROM</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> FactResellerSales </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">UNION </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">SELECT</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">     </span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-tab-count: 1;">      </span>&#8230; </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-tab-count: 1;">      </span><span style="color: gray;">,</span> <span style="color: gray;">NULL</span> <span style="color: blue;">AS</span> [Dummy] </span></p>
<p><span style="font-size: 10pt; color: blue; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: de; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;">FROM</span><span style="font-size: 10pt; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: de; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;"> FactInternetSales</span><br />
<br\><br />
Nun können wir diese Spalte im Cube verwenden und erzeugen uns auf dessen Basis ein neues Measure Namens „Scoped Number of Products“.</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image010.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image010_thumb.jpg" border="0" alt="clip_image010" width="323" height="329" /></a><br />
<br\><br />
Dabei ist zu beachten, dass die Aggregat-Funktion, die bei Usage ausgewählt wird, später auch wirklich Anwendung findet. Während bei berechneten Elementen auf jeder Ebene im Cube die Berechnung stattfindet, wird beim SCOPING „nur“ für den explizit überschriebenen Subcube das MDX verwendet. Für alle nicht überschriebenen Bereiche wird normal aggregiert, wobei allerdings die „neuen“ Werte herangezogen werden.<br />
<br\><br />
Wir wählen also bei Usage die Summe aus und haben unser neues Measure. Nach dem Bereitstellen und Aufbereiten des überarbeiteten Cubes können wir das auch schon verwenden, erhalten aber selbstverständlich nur leere Zellen. Die eigentliche Berechnung müssen wir nun noch unter „Calculations“ definieren:</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">SCOPE</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> ([Measures].[Scoped Number of Products], [Product].[Product].[Product].<span style="color: blue;">MEMBERS</span> ); </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">THIS</span> = 1; </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">SCOPE</span> ([Product].[Product].[All Products].<span style="color: maroon;">UnknownMember</span>); </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">       </span><span style="color: blue;">THIS</span> = 0; </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">END</span> <span style="color: blue;">SCOPE</span>; </span></p>
<p><span style="font-size: 10pt; color: blue; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;" lang="EN-US">END</span><span style="font-size: 10pt; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;" lang="EN-US"> <span style="color: blue;">SCOPE</span>;</span><br />
<br\><br />
Für alle Elemente des Levels “Product” in der Hierarchie “Product” der Dimension “Product” wird damit der Wert des Measures „Scoped Number of Products“ auf 1 gesetzt. Alle anderen Ebenen und Hierarchien, wie z. B. der All-Knoten, werden dabei ignoriert, da wir dafür ja die bereits definierte Summen-Funktion nutzen wollen.<br />
<br\><br />
Um eine Vergleichbarkeit mit dem alten berechneten Element herzustellen, verhindert das zweite SCOPE lediglich, dass das unsichtbare UnknownMember der Produkt-Hierarchie mitgezählt wird.<br />
<br\><br />
Um zu überprüfen, ob die Zahlen passen, nehmen wir das neue Measure nun in unsere erste Abfrage von oben mit auf:</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image012.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image012_thumb.jpg" border="0" alt="clip_image012" width="476" height="145" /></a><br />
<br\><br />
Soweit, so gut. Spannender wird es jetzt aber, wenn wir die Kategorien wieder von den Zeilen in den Filter verschieben und nur die ersten beiden Elemente auswählen &#8211; Excel also wieder sein beliebtes SUBSELECT ausführt:</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image014.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image014_thumb.jpg" border="0" alt="clip_image014" width="321" height="106" /></a><br />
<br\><br />
Wie erhofft ergibt 35 + 125 nun nicht mehr 606, sondern Excel gibt die korrekte Summe 160 zurück. Dadurch, dass wir das Measure auf der untersten Ebene der Produktdimension überschrieben haben, nutzen die Analysis Services nicht mehr bestehende Aggregate, sondern müssen alle betroffenen Produkte zur Laufzeit berechnen. Die anschließend stattfindende Aggregation der Werte wird dann nur für den betroffenen Subcube, also unter Berücksichtigung des Subselects, durchgeführt.<br />
<br\><br />
Um zu zeigen, dass dies nicht nur für simples Zählen funktioniert, erzeugen wir uns ein weiteres Measure auf Basis unserer Dummy-Spalte, nennen es „Scoped Ratio to Parent Product“ und erweitern unser MDX-Script um folgenden Ausdruck:</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; color: blue; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US">SCOPE</span><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"> ([Measures].[Scoped Ratio to Parent Product], [Product].[Product Model Categories].<span style="color: blue;">MEMBERS</span>); </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">SCOPE</span>(<span style="color: blue;">DESCENDANTS</span>([Product].[Product Model Categories].[All Products], , <span style="color: blue;">AFTER</span>)); </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">        </span><span style="color: blue;">THIS</span> = [Measures].[Sales Amount] </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">             </span>/ ( [Product].[Product Model Categories].<span style="color: maroon;">CurrentMember</span>.<span style="color: maroon;">Parent</span>, </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">               </span>[Measures].[Sales Amount] ); </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">END</span> <span style="color: blue;">SCOPE</span>; </span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; line-height: normal; mso-pagination: none; mso-layout-grid-align: none;"><span style="font-size: 10pt; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us;" lang="EN-US"><span style="mso-spacerun: yes;">    </span><span style="color: blue;">Format_String</span>(<span style="color: blue;">THIS</span>) = <span style="color: #a31515;">&#8220;Percent&#8221;</span> ; </span></p>
<p><span style="font-size: 10pt; color: blue; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;" lang="EN-US">END</span><span style="font-size: 10pt; line-height: 115%; font-family: &amp;#39;Courier New&amp;#39;; mso-ansi-language: en-us; mso-fareast-font-family: calibri; mso-fareast-theme-font: minor-latin; mso-fareast-language: en-us; mso-bidi-language: ar-sa;" lang="EN-US"> <span style="color: blue;">SCOPE</span>;</span><br />
<br\><br />
Dabei sorgt das DESCENDANTS(…) dafür, dass alle Elemente der Hierarchie “Product Model Categories” außer dem All-Knoten überschrieben werden. Das Ergebnis in Excel sieht dann folgendermaßen aus:</p>
<p><a href="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image016.jpg"><img style="border-width: 0px;" src="http://blog.ixtoprod.s15244651.onlinehome-server.info/blogbilder/KorrekteMDXBerechnungenmitdenAnalysisSer_87F6/clip_image016_thumb.jpg" border="0" alt="clip_image016" width="387" height="106" /></a><br />
<br\><br />
Auch hier sorgt das Überschreiben auf unterster Ebene dafür, dass die Berechnung richtig funktioniert. In dem Augenblick, in dem die einzelnen Knoten der ausgewerteten Hierarchie berechnet werden, gibt es eben immer ein CurrentMember, egal ob nun ein oder mehrere Knoten ausgewählt sind.<br />
<br\><br />
<strong><span style="text-decoration: underline;">Einschränkungen</span></strong><br />
<br\><br />
Zugegeben, habe ich mir das ganze hier etwas leicht gemacht. Die beiden Berechnungen einfach zu summieren, macht nämlich eigentlich keinen Sinn. Sowohl die Anzahl der Produkte, als auch die Prozente sind sogenannte semi-additive Measures, die eben nicht einfach summiert werden dürfen. Für beide fehlt also mindestens eine Sonderbehandlung für die Zeitdimension, die durch Nutzung anderer Aggregatfunktionen oder erweiterter SCOPE-Statements erreicht werden könnte, die den Rahmen dieses Beitrags sprengen würden.<br />
<br\><br />
Außerdem muss ich davor warnen jetzt ab sofort alle berechneten Elemente durch solche SCOPEs abzulösen, denn das ganze hat natürlich einen Haken. Der Grund, warum das Ganze funktioniert, nämlich das Berechnen auf unteren Ebenen, hat gleichzeitig negative Auswirkungen auf die Performance. Es können eben nicht mehr vorberechnete Werte aus den Aggregationen oder dem Cache übernommen werden. Bei jeder Abfrage, die sonst nur wenige Zellen zur Berechnung hätte nutzen müssen, muss jetzt unter Umständen ein Vielfaches an Daten berücksichtigt werden, um das gewünschte Ergebnis zu erhalten.<br />
<br\><br />
Nichts desto trotz zeigt das Ganze, dass es möglich ist, Berechnungen so zu definieren, dass sie Multiselect-fähig sind, obwohl sie Funktionen wie EXISTING oder CurrentMember benötigen. Wer mit relativ wenig Daten arbeitet, oder wem es nicht gelingt seinen Nutzern das Multiselect in Excel auszureden, der kommt so vielleicht zu einer Lösung.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ixto.de/blog/sql-server-2005/mdx-2005/korrekte-mdx-berechnungen-mit-den-analysis-services-trotz-multiselect/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dimensionsdatensicherheit als Fehlerquelle f&#252;r &quot;unsaubere&quot; Sets</title>
		<link>http://www.ixto.de/blog/sql-server-2005/mdx-2005/dimensionsdatensicherheit-als-fehlerquelle-fr-unsaubere-sets/</link>
		<comments>http://www.ixto.de/blog/sql-server-2005/mdx-2005/dimensionsdatensicherheit-als-fehlerquelle-fr-unsaubere-sets/#comments</comments>
		<pubDate>Mon, 28 Jul 2008 16:44:39 +0000</pubDate>
		<dc:creator>Markus Schechner</dc:creator>
				<category><![CDATA[MDX im SQL Server 2005]]></category>

		<guid isPermaLink="false">http://www.ixto.de/blog/allgemein/dimensionsdatensicherheit-als-fehlerquelle-fr-unsaubere-sets/</guid>
		<description><![CDATA[Hallo liebe Reportbauer, MDXler und alle die es werden wollen,
ich bin vor kurzem bei einem Kunden &#252;ber ein Ph&#228;nomen gestolpert, dass ich Euch nicht vorenthalten will.
&#160;
Wie immer wieder von mir gepredigt wird, arbeiten wir in der Regel zur Ausklammerung bestimmter Dimensionsknoten mit so genannten &#8222;Negativ-Listen&#8220;. Das bedeutet, wenn wir aus der Dimension Buchstaben die Knoten [...]]]></description>
			<content:encoded><![CDATA[<p>Hallo liebe Reportbauer, MDXler und alle die es werden wollen,</p>
<p>ich bin vor kurzem bei einem Kunden &#252;ber ein Ph&#228;nomen gestolpert, dass ich Euch nicht vorenthalten will.</p>
<p>&#160;</p>
<p>Wie immer wieder von mir gepredigt wird, arbeiten wir in der Regel zur Ausklammerung bestimmter Dimensionsknoten mit so genannten &#8222;Negativ-Listen&#8220;. Das bedeutet, wenn wir aus der Dimension Buchstaben die Knoten A, B und E sehen wollen sagen wir nicht {A, B, E} sondern {Buchstaben.ALLE &#8211; {C, D}}. Dadurch w&#252;rden neue Knoten in der Dimension (z.B. der neu eingef&#252;hrte Buchstabe F <img src='http://www.ixto.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ) nicht per Default unterdr&#252;ckt, sondern w&#228;ren erst mal sichtbar. In den meisten echten Anwendungsf&#228;llen ist diese Negativ-Liste oft auch deutlich k&#252;rzer als die Positiv-Liste.<br />
<span id="more-35"></span> <br\> Aber genug &#252;ber den Sinn und Unsinn von Negativ-Listen, das Statement</p>
<p>&#160;</p>
<p><font color="#0000ff" size="2">SELECT</font>
</p>
<p>   <font size="2">{}</font>
<p><font color="#0000ff" size="2">ON</font><font size="2"> </font><font color="#0000ff" size="2">COLUMNS</font><font size="2">,</font></p>
<p>{[Product].[Category].[Accessories], [Product].[Category].[Bikes], [Product].[Category].[Clothing]}</p>
<p><font color="#0000ff" size="2">ON</font><font size="2"> </font><font color="#0000ff" size="2">ROWS</font></p>
<p>FROM</p>
<p><font size="2">[Adventure Works]</font></p>
<p>&#160;</p>
</p>
<p> liefert das gleiche Ergebnis zur&#252;ck, wie</p>
<p>&#160;</p>
<p><font color="#0000ff" size="2">SELECT</font>
</p>
<p>   <font size="2">{}</font>
<p><font color="#0000ff" size="2">ON</font><font size="2"> </font><font color="#0000ff" size="2">COLUMNS</font><font size="2">,</font></p>
<p>{[Product].[Category].[Category].</p>
<p><font color="#0000ff" size="2">MEMBERS</font><font size="2"> &#8211; [Product].[Category].[Components]} </font><font color="#0000ff" size="2">ON</font><font size="2"> </font><font color="#0000ff" size="2">ROWS</font></p>
<p>FROM</p>
<p><font size="2">[Adventure Works]</font></p>
<p>&#160;</p>
</p>
<p> Nun hat sich innerhalb des besagten Kundenprojektes heimlich durchgesetzt, dass die abgek&#252;rzte Schreibweise verwendet wird, also {&#8211; {C, D}} statt { Buchstaben.ALLE &#8211; {C, D}}. Also auch die folgende dritte Variante hat das gleiche Ergebnis wie die oberen beiden.</p>
<p>&#160;</p>
<p><font color="#0000ff" size="2">SELECT</font>
</p>
<p>   <font size="2">{}</font>
<p><font color="#0000ff" size="2">ON</font><font size="2"> </font><font color="#0000ff" size="2">COLUMNS</font><font size="2">,</font></p>
<p>{-{[Product].[Category].[Components]}}</p>
<p><font color="#0000ff" size="2">ON</font><font size="2"> </font><font color="#0000ff" size="2">ROWS</font></p>
<p>FROM</p>
<p><font size="2">[Adventure Works]</font></p>
<p>&#160;</p>
</p>
<p> Dies hat eigentlich auch super funktioniert, ist an K&#252;rze kaum noch zu &#252;bertreffen UND SOLLTE TROTZDEM NIE WIEDER GETAN WERDEN <img src='http://www.ixto.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>&#160;</p>
<p>Implizit erkennt der AS bei dieser Schreibweise, welche Elemente auf der linken Seite dieses Komplements geh&#246;ren, n&#228;mlich Buchstaben.ALLE. Sobald aber eine Dimensionssicherheit ins Spiel kommt wird&#8217;s gef&#228;hrlich. AS sucht die Knoten dann nur noch in dem Bereich in dem der Nutzer berechtigt ist. Wenn er den Knoten da nicht findet, wei&#223; er nicht, ob er nicht existiert, oder ob er nicht berechtigt ist und ersetzt ihn durch die leere Menge ({}).</p>
<p>&#160;</p>
<p>Aus { Buchstaben.ALLE &#8211; {C, D}} w&#252;rde also intern { Buchstaben.ALLE &#8211; { }}. Nicht schlimm, funktioniert super. Ihr k&#246;nnt Euch aber denken, dass das nicht mehr funktioniert, wenn aus {&#8211; {C, D}} durch dieses Verhalten {-{}} wird. Und das B&#246;se daran ist, dass das erst auftritt wenn der erste eingeschr&#228;nkte Nutzer darauf zugreift. F&#252;r Euch als Entwickler sieht es aus als w&#228;re alles fein, w&#228;hrend der arme Benutzer mit der Meldung &quot;<em>Die Menge muss eine einzige Hierarchie aufweisen, um mit dem Komplementoperator verwendet zu werden.</em>&quot; bzw. &quot;<em>The set must have a single hierarchy to be used with the complement operator.</em>&quot; begr&#252;&#223;t wird.</p>
<p>&#160;</p>
<p>Also kurz:</p>
<p>Niemals {&#8211; {C, D}}</p>
<p>Immer { Buchstaben.ALLE &#8211; {C, D}}&#160; oder aber EXCEPT(Buchstaben.ALLE, {C, D})</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ixto.de/blog/sql-server-2005/mdx-2005/dimensionsdatensicherheit-als-fehlerquelle-fr-unsaubere-sets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

