<?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>Purple Frog Systems &#187; Analysis Services</title>
	<atom:link href="http://www.purplefrogsystems.com/blog/tag/analysis-services/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.purplefrogsystems.com/blog</link>
	<description>Business Intelligence Consultancy</description>
	<lastBuildDate>Mon, 23 Jan 2012 09:11:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Video: Automating SSAS OLAP Cube documentation</title>
		<link>http://www.purplefrogsystems.com/blog/2011/05/video-automating-ssas-olap-cube-documentation/</link>
		<comments>http://www.purplefrogsystems.com/blog/2011/05/video-automating-ssas-olap-cube-documentation/#comments</comments>
		<pubDate>Thu, 26 May 2011 12:48:04 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Reporting Services]]></category>
		<category><![CDATA[Cube]]></category>
		<category><![CDATA[Documentation]]></category>
		<category><![CDATA[SQLBits]]></category>
		<category><![CDATA[SSAS]]></category>
		<category><![CDATA[Star Schema]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=394</guid>
		<description><![CDATA[Automating OLAP cube documentation &#8211; SQLBits presentation For anyone that missed my presentation at SQLBits 8 in April, the video is now available here. In this 1 hour session I present a method of automating the creation of documentation for SSAS OLAP cubes by using DMVs (dynamic management views) and spatial data, querying the metadata [...]]]></description>
			<content:encoded><![CDATA[<h1>Automating OLAP cube documentation &#8211; SQLBits presentation</h1>
<p>For anyone that missed my presentation at SQLBits 8 in April, <a href="http://sqlbits.com/Sessions/Event8/Automating_SSAS_cube_documentation_using_SSRS_DMV_and_Spatial_Data">the video is now available here</a>.</p>
<p><br/></p>
<p>In this 1 hour session I present a method of automating the creation of documentation for SSAS OLAP cubes by using DMVs (dynamic management views) and spatial data, querying the metadata of the cube in realtime.</p>
<p>The results include the BUS matrix, star schemas, attribute lists, hierarchies etc. and are all presented in SSRS.</p>
<p><br/></p>
<p><a href="http://sqlbits.com/Sessions/Event8/Automating_SSAS_cube_documentation_using_SSRS_DMV_and_Spatial_Data"><img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/05/SQLBits8Video_m-300x164.jpg" alt="" title="SQLBits8Video_m" width="300" height="164" class="alignleft size-medium wp-image-397" /></a>The blog posts to go with this are here:</p>
<ul>
<li><a href="/blog/2010/09/olap-cube-documentation-in-ssrs-part-1/">Part 1</a></li>
<li><a href="/blog/2010/09/olap-cube-documentation-in-ssrs-part-2/">Part 2</a></li>
<li><a href="/blog/2010/09/olap-cube-documentation-in-ssrs-part-3/">Part 3</a></li>
</ul>
<p><br/></p>
<p>You can view the slide deck <a href="http://bit.ly/cubedocslides">here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2011/05/video-automating-ssas-olap-cube-documentation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Business Intelligence Semantic Model (BISM)</title>
		<link>http://www.purplefrogsystems.com/blog/2011/05/the-business-intelligence-semantic-model-bism/</link>
		<comments>http://www.purplefrogsystems.com/blog/2011/05/the-business-intelligence-semantic-model-bism/#comments</comments>
		<pubDate>Wed, 18 May 2011 12:54:43 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[PowerPivot]]></category>
		<category><![CDATA[BISM]]></category>
		<category><![CDATA[Denali]]></category>
		<category><![CDATA[UDM]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=389</guid>
		<description><![CDATA[I&#8217;m a happy chap. Why? Because I read a blog post yesterday by T.K. Anand (SSAS Principal Group Program Manager) about the vision and roadmap of Analysis Services. There were slightly concerning questions last November (following the PASS conference) surounding the future of Analysis Services, or more specifically the UDM, the dimensional model that we [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/05/denali.png" alt="" title="denali" width="214" height="79" class="alignright size-full wp-image-390" />
<p>I&#8217;m a happy chap. Why? Because I read a blog post yesterday by T.K. Anand (SSAS Principal Group Program Manager) about the <a href="http://blogs.msdn.com/b/powerpivot/archive/2011/05/16/analysis-services-vision-amp-roadmap-update.aspx">vision and roadmap of Analysis Services</a>.</p>
<p>There were slightly concerning questions last November (following the PASS conference) surounding the future of Analysis Services, or more specifically the UDM, the dimensional model that we all know and love in SSAS 2005 &#038; 2008. The arrival of PowerPivot into the Microsoft BI arsenal has without a doubt moved the goalposts and added significant power, flexibility and usability to the BI stack. My concern, along with others (most notibly <a href="http://cwebbbi.wordpress.com/2011/05/17/good-news-on-the-future-of-analysis-services/">Chris Webb</a>, who sparked somewhat of a stampede on the issue), was for the future of the UDM and the multitude of existing dimensional systems out in the field. Is the dimensional approach being phased out? Will it be supported in future editions? Will it be enhanced? Will the future BISM support the complexity and power we currently have with the UDM?</p>
<p>There&#8217;s no doubt that the overall approach to business intelligence is evolving. And this isn&#8217;t just in the cube space, it obviously has a direct effect on all other aspects of the BI strategy; the data warehouse, reporting layer, ETL etc.</p>
<p><br/></p>
<p>From a BI consultant&#8217;s point of view, I don&#8217;t want to be recommending tools to my clients which have a restricted life span and don&#8217;t provide them a future proof upgrade path.</p>
<p>From a technology perspective, I&#8217;m a hardened supporter of the dimensional model. I recently designed a complex cube system for a banking client which had over 150 dimensions and facts, with thousands of lines of MDX to create a very sophisticated calculation framework for their liquidity modelling and loan profiling. I wouldn&#8217;t dream of doing that in a tabular approach like PowerPivot (in their current form).</p>
<p>From a personal point of view, where do I focus my attention in terms of training, research, blogging, user groups, conference sessions etc. etc.</p>
<p><br/></p>
<p>I should point out that I&#8217;m very excited by, and fully committed to the tabular/PowerPivot route (along with VertiPaq, Crescent, DAX, etc.) for systems that it is suited to. In fact I&#8217;m using it right now to prototype a global BI solution for a very large client. There are however some solutions that do not fit well with the tabular approach and are best suited to a dimensional approach. I&#8217;m in favour of a hybrid framework which allows the right tool to be used for the right system. And it looks like that&#8217;s what we&#8217;re going to get.</p>
<p>The guys at Microsoft have now evolved and clarified the roadmap, and have confirmed that the BISM (business intelligence semantic model, i.e. The core of Analysis Services in SQL Server Denali) will contain two parallel approaches that can both be used for whichever situations they are best suited to. More importantly, they are both here to stay, will both be developed further, and there will be a cross-availability of functionality and tools between them.</p>
<h2>Multi Dimensional Model</h2>
<p>Essentially the same as the existing UDM, the multi-dimensional data model will support MDX and ROLAP/MOLAP data access. Existing OLAP cubes in SQL 2008 will easily upgrade to this.</p>
<h2>Tabular Model</h2>
<p>Think of this as hosted PowerPivot. A tabular approach with a column based data store, DAX as the expression language and either VertiPaq or Direct Query for data access.</p>
<p><br/></p>
<p>The two will co-exist side by side within a singluar BISM, albeit initially with a degree of seperation. In the upcoming CTP2 release (July 2011?) there will not be any cross-availability of functionality, i.e. VertiPaq, Crescent and DAX will not be available to the dimensional model. However TK makes it clear that this is a short term restriction in the CTP, and that Microsoft are commited to getting this cross availability in place in the finished product.</p>
<p>If you&#8217;re involed in BI in any way, I really do encourage you to go and read <a href="http://blogs.msdn.com/b/powerpivot/archive/2011/05/16/analysis-services-vision-amp-roadmap-update.aspx">TK&#8217;s post</a> in detail. The Business Intelligence world is changing. I now have total confidence that it&#8217;s for the better.</p>
<p>Frog-blog-out</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2011/05/the-business-intelligence-semantic-model-bism/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Debug MDX queries using Drillthrough in SSMS</title>
		<link>http://www.purplefrogsystems.com/blog/2011/02/debug-mdx-queries-using-drillthrough-in-ssms/</link>
		<comments>http://www.purplefrogsystems.com/blog/2011/02/debug-mdx-queries-using-drillthrough-in-ssms/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 18:30:31 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Cube]]></category>
		<category><![CDATA[Drillthrough]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[OLAP]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=311</guid>
		<description><![CDATA[One of the great features of using Excel to browse an SSAS OLAP cube is the drillthrough ability. If you double click on any cell of an OLAP pivot table, Excel will create a new worksheet containing the top 1000 fact records that went to make up the figure in the selected cell. N.B. The [...]]]></description>
			<content:encoded><![CDATA[<p>One of the great features of using Excel to browse an SSAS OLAP cube is the drillthrough ability. If you double click on any cell of an OLAP pivot table, Excel will create a new worksheet containing the top 1000 fact records that went to make up the figure in the selected cell.</p>
<p><img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/02/MDXDrillthrough0-1024x598.png" alt="" title="MDXDrillthrough0" width="600" height="350" class="aligncenter size-large wp-image-312" /></p>
<p>N.B. <a href="/blog/2010/03/excel-cube-pivot-drillthrough-limited-to-1000-rows/">The limit of 1000 rows can be altered</a>, as per one of my previous blog posts <a href="">here</a>.</p>
<p><br/></p>
<p>This feature is pretty well known, but not many folk realise how easy it is to reproduce this in SQL Server Management Studio (SSMS). All you need to do is prefix your query with DRILLTHROUGH.</p>
<p>i.e. Assuming an MDX query of</p>
<p class="code">SELECT [Measures].[Internet Sales Amount] ON 0<br />
FROM [Adventure Works]<br />
WHERE [Date].[January 1, 2004]
</p>
<p>Which returns the following results&#8230;</p>
<p><img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/02/MDXDrillthrough1.png" alt="" title="MDXDrillthrough1" width="406" height="153" class="aligncenter size-full wp-image-313" /></p>
<p>A query of</p>
<p class="code">DRILLTHROUGH<br />
SELECT [Measures].[Internet Sales Amount] ON 0<br />
FROM [Adventure Works]<br />
WHERE [Date].[January 1, 2004]
</p>
<p>Returns the records contributing to the total figure. Great for diagnosing problems with an MDX query.</p>
<p><img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/02/MDXDrillthrough2.png" alt="" title="MDXDrillthrough2" width="609" height="335" class="aligncenter size-full wp-image-314" /></p>
<p>By default, only the first 10,000 rows are returned, but you can override this using MAXROWS</p>
<p class="code">DRILLTHROUGH MAXROWS 500<br />
SELECT [Measures].[Internet Sales Amount] ON 0<br />
FROM [Adventure Works]<br />
WHERE [Date].[January 1, 2004]
</p>
<p>The columns that are returned are those defined in the Actions tab of the Cube Designer in BIDS (The Business Intelligence Development Studio).</p>
<p><img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/02/MDXDrillthrough31.png" alt="" title="MDXDrillthrough3" width="597" height="298" class="aligncenter size-full wp-image-321" /></p>
<p>If no action is defined, then the fact measures will be returned along with the keys that link to each relevant dimension, which tend not to be that helpful.</p>
<p><br/>
<p>You can override the returned columns by using the RETURN clause</p>
<pre>
<p class="code">DRILLTHROUGH
SELECT [Measures].[Internet Sales Amount] ON 0
FROM [Adventure Works]
WHERE [Date].[January 1, 2004]
RETURN
   [$Internet Sales Order Details].[Internet Sales Order]
  ,[$Sales Territory].[Sales Territory Region]
  ,NAME([$Product].[Product])
  ,KEY([$Product].[Product])
  ,UNIQUENAME([$Product].[Product])
  ,[Internet Sales].[Internet Sales Amount]
  ,[Internet Sales].[Internet Order Quantity]

</pre>
<p>
<img src="http://www.purplefrogsystems.com/blog/wp-content/uploads/2011/02/MDXDrillthrough41.png" alt="" title="MDXDrillthrough4" width="596" height="401" class="aligncenter size-full wp-image-320" /><br />
<br/></p>
<p>Note that there are some restrictions on what you can drill through</p>
<ul>
<li>You can&#8217;t drill through an expression/calculation, only a raw measure
<li>The MDX query needs to return a single cell (otherwise the cube does not know which one to drill through)
<li>The data returned will be at the lowest granularity of the cube&#8217;s fact table
</ul>
</p>
<p>To explain the last point further, the cube does not return the raw data from the underlying data warehouse, but a summary of the facts grouped by unique combination of the relevant dimensions. i.e. if a warehouse table containing individual sales (by date, product, customer &#038; store) is brought into a cube as a fact table that only has relationships with the date and product dimensions, then the cube drill through will return unique combinations of date and product, summarising sales for each combination. Extra granularity which the warehouse may contain (customer and store) will not be available.</p>
<p>Note that if you specify the RETURN columns, the rows are still returned at the lowest level of the fact table granularity, even if not all of the dimensions are brought out as columns. This may result in returning multiple identical records. Don&#8217;t worry, these will be distinct facts, just differentiated by a dimension/attribute that isn&#8217;t being returned.</p>
<p align="right">You can find out more on <a href="http://technet.microsoft.com/en-us/library/ms145964.aspx" target="_blank">TechNet here</a></p>
<p><br/></p>
<p>Frog-Blog Out</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2011/02/debug-mdx-queries-using-drillthrough-in-ssms/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to add calculations in SSAS cubes</title>
		<link>http://www.purplefrogsystems.com/blog/2011/01/how-to-add-calculations-in-ssas-cubes/</link>
		<comments>http://www.purplefrogsystems.com/blog/2011/01/how-to-add-calculations-in-ssas-cubes/#comments</comments>
		<pubDate>Sun, 16 Jan 2011 14:33:30 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Calculated Member]]></category>
		<category><![CDATA[Cube]]></category>
		<category><![CDATA[DSV]]></category>
		<category><![CDATA[SSAS]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=300</guid>
		<description><![CDATA[One of the most useful aspects of a Business Intelligence system is the ability to add calculations to create new measures. This centralises the logic of the calculation into a single place, ensuring consistency and standardisation across the user base. By way of example, a simple calculation for profit (Income – Expenditure) wouldn’t be provided [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most useful aspects of a Business Intelligence system is the ability to add calculations to create new measures. This centralises the logic of the calculation into a single place, ensuring consistency and standardisation across the user base.</p>
<p>By way of example, a simple calculation for profit (Income – Expenditure) wouldn’t be provided by the source database and historically would be implemented in each and every report. In a data warehouse and/or cube we can create the calculation in a single place for everyone to use.</p>
<p>This post highlights some of methods of doing this, each with their respective pros and cons. </p>
<h2>Calculated Members in SSAS Cube</h2>
<p><img src="/images/blog/SSASCalculatedMember.png" align="center"><br />
SSAS provides a ‘Calculations’ tab in the cube designer which allows you to create new measures using MDX. You can use any combination of existing measures and dimension attributes, along with the plethora of MDX functions available to create highly complex calculations.<br />
<strong>Pros:</strong></p>
<ul>
<li>Very complex calculations can be created using all available MDX functions</li>
<li>No changes are required to the structure of the data warehouse</li>
<li>Changes to the calculation will apply to every record, historic and new </li>
<li>The results are not stored in the warehouse or cube, so no extra space is required</li>
<li>New calculations can be added without having to deploy or reprocess the cube</li>
<li>Calculations can be scoped to any level of aggregation and granularity. Different calculations can even be used for different scopes</li>
<li>Calculations can easily combine measures from different measure groups</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>The calculation will not make use of SSAS cube aggregations, reducing performance</li>
<li>SSAS drill through actions will not work</li>
<li>The calculation results are not available in the data warehouse, only the cube</li>
</ul>
<h2>SQL Calculations in the Data Source View</h2>
<p><img src="/images/blog/SSASDSVQuery.png" align="center"><br />
There’s a layer in-between the data warehouse and the cube called the data source view (DSV). This presents the relevant tables in the warehouse to the cube, and can be used to enhance the underlying data with calculations. This can either be the dsv layer within the cube project, or I prefer to create SQL Server views to encapsulate the logic.<br />
<strong>Pros:</strong></p>
<ul>
<li>No changes are required to the table structure of the data warehouse</li>
<li>Calculations use SQL not MDX, reducing the complexity</li>
<li>Changes to the calculation will apply to every record, historic and new </li>
<li>The calculation will make full use of SSAS cube aggregations</li>
<li>SSAS drill through actions will work</li>
<li>The results are not stored in the warehouse, so the size of the database does not increase</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>The cube must be redeployed and reprocessed before the new measure is available</li>
<li>The results of the calculation must be valid at the granularity of the fact table</li>
<li>The calculation results are not available in the data warehouse, only the cube</li>
</ul>
<h2>Calculate in the ETL process</h2>
<p><img src="/images/blog/ETLCalculation.png" align="center"><br />
Whilst bringing in data from the source data systems, it sometimes makes sense to perform calculations on the data at that point, and store the results in the warehouse.<br />
<strong>Pros:</strong></p>
<ul>
<li>The results of the calculation will be available when querying the warehouse as well as the cube</li>
<li>In the ETL pipeline you can import other data sources (using lookups etc.) to utilise other data in the calculation</li>
<li>If the calculation uses time based data, or data valid at a specific time (i.e. share price) then by performing the calculation in the ETL, the correct time based data is used, without having to store the full history of the underlying source data</li>
<li>The calculation will make full use of SSAS cube aggregations</li>
<li>SSAS drill through actions will work</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li>You have to be able to alter the structure of the data warehouse, which isn’t always an option.</li>
<li>The results are stored in the warehouse, increasing the size of the database</li>
<li>The results of the calculation must be valid at the granularity of the fact table</li>
<li>If the calculation logic changes, all existing records must be updated</li>
</ul>
<p><br/></p>
<h2>In Conclusion</h2>
<p>If the calculation is valid for a single record, and it would be of benefit to have access to the results in the warehouse, then perform the calculation in the ETL pipeline and store teh results in the warehouse.</p>
<p>If the calculation is valid for a single record, and it would not be of benefit to have the results in the warehouse, then calculate it in the data source view.</p>
<p>If the calculation is too complex for SQL, requiring MDX functions, then create an MDX calculated measure in the cube.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2011/01/how-to-add-calculations-in-ssas-cubes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MDX Calculated Member Spanning Multiple Date Dimensions</title>
		<link>http://www.purplefrogsystems.com/blog/2010/08/mdx-calculated-member-spanning-multiple-date-dimensions/</link>
		<comments>http://www.purplefrogsystems.com/blog/2010/08/mdx-calculated-member-spanning-multiple-date-dimensions/#comments</comments>
		<pubDate>Thu, 05 Aug 2010 17:09:51 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Calculated Member]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[Semi Additive]]></category>
		<category><![CDATA[SSAS]]></category>
		<category><![CDATA[Time Dimension]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=140</guid>
		<description><![CDATA[It’s common in most cubes to have a number of different date dimensions, whether role playing, distinct, or a combination of both. Say for example, Entry Date, Posting Date and Accounting Period. There may also be numerous hierarchies in each date dimension, such as calendar and fiscal calendar, leading to a relatively complicated array of [...]]]></description>
			<content:encoded><![CDATA[<p>It’s common in most cubes to have a number of different date dimensions, whether role playing, distinct, or a combination of both. Say for example, Entry Date, Posting Date and Accounting Period. There may also be numerous hierarchies in each date dimension, such as calendar and fiscal calendar, leading to a relatively complicated array of dates to worry about when calculating semi-additive measures.</p>
<p>If we create a date related calculation (i.e. total to date) how do we ensure that this calculation works across all date dimensions?</p>
<p>Lets assume we have a stock movement measure, where each record in the fact table is the change in stock (plus or minus). The current stock level is found by using a calculation totaling every record to date.</p>
<pre><span style="color: #008000;">CREATE MEMBER CURRENTCUBE.[Measures].[Stock Level]
AS
  SUM({NULL:[Date].[Calendar].CurrentMember}
     , [Measures].[Stock Movement]
  );
</span></pre>
<p>[Note that {NULL:xxx} just creates a set of everything before the xxx member, i.e. everything to date]</p>
<p>This works just fine, if the user selects the [Date].[Calendar] hierarchy. What if the user selects the [Date].[Fiscal] hierarchy, or the [Period] dimension? Basically the calculation wont work, as the MDX expression is only aware of the [Date].[Calendar] hierarchy.</p>
<p>The simple solution is to use the Aggregate function over all of the dimensions that the calculation needs to be aware of:</p>
<pre><span style="color: #008000;">CREATE MEMBER CURRENTCUBE.[Measures].[Stock Level]
AS
  AGGREGATE(
      {NULL:[Date].[Fiscal].CurrentMember}
       * {NULL:[Date].[Calendar].CurrentMember}
       * {NULL:[Period].[Period].CurrentMember}
    , [Measures].[Stock Movement]
  );
</span></pre>
<p>The calculation will then use whichever date or time hierarchy is selected. It will even cope if multiple dimensions are selected, say the calendar on 0 and the periods on 1, both axis will honor the aggregation as expected.</p>
<p>Frog-Blog out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2010/08/mdx-calculated-member-spanning-multiple-date-dimensions/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>MDX Sub select Vs WHERE clause</title>
		<link>http://www.purplefrogsystems.com/blog/2010/03/mdx-sub-select-vs-where-clause/</link>
		<comments>http://www.purplefrogsystems.com/blog/2010/03/mdx-sub-select-vs-where-clause/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 09:23:15 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Cube]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[WHERE]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=36</guid>
		<description><![CDATA[I&#8217;ve just read an interesting thread on the SQL Server Developer Center forum, regarding how to filter results. Specifically the difference in MDX between using a subselect SELECT x on COLUMNS, y on ROWS FROM ( SELECT z on COLUMNS FROM cube)) or using a where clause SELECT x on COLUMNS, y on ROWS FROM [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just read an interesting thread on the SQL Server Developer Center forum, regarding how to filter results. Specifically the difference in MDX between using a subselect</p>
<pre>
<p class="code">SELECT x on COLUMNS, y on ROWS
FROM ( SELECT z on COLUMNS FROM cube))

</pre>
<p>or using a where clause</p>
<pre>
<p class="code">SELECT x on COLUMNS, y on ROWS
FROM cube
WHERE z

</pre>
<p>In a simple query they produce the same results, but what is the actual difference? You can read the full thread <a href="http://social.msdn.microsoft.com/Forums/en-US/sqlanalysisservices/thread/3f0a2aba-93de-4f67-8402-181798a6225f" target="_blank">here</a>, but to summarise Darren Gosbell&#8217;s response&#8230;</p>
<p>Using the WHERE clause sets the query context and consequently the CurrentMember. This then enables functions such as YTD and PerdiodsToDate to work.</p>
<p>Using a subselect can provide improved performance, but does not set the context.</p>
<p>Simples..!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2010/03/mdx-sub-select-vs-where-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Excel 2007 and SSAS 2008 Error</title>
		<link>http://www.purplefrogsystems.com/blog/2009/10/excel-2007-and-ssas-2008-error/</link>
		<comments>http://www.purplefrogsystems.com/blog/2009/10/excel-2007-and-ssas-2008-error/#comments</comments>
		<pubDate>Fri, 30 Oct 2009 16:56:06 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[Pivot]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=20</guid>
		<description><![CDATA[I was working on a new SSAS 2008 cube today, and came across an error which Google was unable to help with. I thought I&#8217;d post the solution here to help anyone else who may encounter it. The cube in question will be primarily be accessed using Excel 2007, so I&#8217;d been dutifully testing it [...]]]></description>
			<content:encoded><![CDATA[<p>I was working on a new SSAS 2008 cube today, and came across an error which Google was unable to help with. I thought I&#8217;d post the solution here to help anyone else who may encounter it.</p>
<p>The cube in question will be primarily be accessed using Excel 2007, so I&#8217;d been dutifully testing it along the way to ensure all was well. And then, after a number of changes the following error appeared when connecting to the cube from Excel to create a pivot table.</p>
<p><span style="color: #008000;">Excel was unable to get necessary information about this cube. The cube might have been reorganized or changed on the server.</p>
<p>Contact the OLAP cube administrator and, if necessary, set up a new data source to connect to the cube<br />
</span></p>
<p>Connecting and querying the cube via SSMS or BIDS worked without error (hense I didn&#8217;t spot the error sooner!).</p>
<p>A quick Google revealed a number of posts regarding this error, but they all related to attributes containing <a href="http://support.microsoft.com/kb/210806" target="_blank">invalid characters</a> when accessed from Excel 2000 Or problems with <a href="http://social.msdn.microsoft.com/Forums/en-US/sqlanalysisservices/thread/22796693-6060-483c-9071-84965d3536a7" target="_blank">translations and locale settings</a> in the .oqy file. Neither of these was the cause here, so I had to go back and recreate every change I had made step by step to track the problem.</p>
<p>Well, I&#8217;m please to report that in the end it was nothing more that a simple spelling mistake in a named set. One of the dynamic named sets in the cube calculations referred to a specific member of a dimension, which was spelled slightly incorrectly. (Simplified example..)</p>
<pre><span style="color: #008000;">CREATE DYNAMIC SET CURRENTCUBE.[Set1]
 AS {[Dimension].[Attribute].[Value1],
     [Dimension].[Attribute].[Value2WithTypo]
    };
</span></pre>
<p>When querying calculated measures through MDX in SSMS, the MDX parser just ignored the problem and only uses the valid members, however it appears as though Excel 2007 is slightly more picky with its cubes.</p>
<p>Useful to know, and even more useful when used as a tool to double check for any errors in the MDX calculations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2009/10/excel-2007-and-ssas-2008-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mosha&#039;s MDX Studio</title>
		<link>http://www.purplefrogsystems.com/blog/2008/09/moshas-mdx-studio/</link>
		<comments>http://www.purplefrogsystems.com/blog/2008/09/moshas-mdx-studio/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 16:03:38 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[Cube]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[Mosha]]></category>
		<category><![CDATA[OLAP]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=17</guid>
		<description><![CDATA[I almost feel embarrassed&#8230;, I&#8217;ve been writing this blog for over 9 months now, and I have yet to mention Mosha, although in my defence, there is a link to his blog in the links section to the right. As many/most of you may know, Mosha Pasumansky is one the key brains behind designing the [...]]]></description>
			<content:encoded><![CDATA[<p>I almost feel embarrassed&#8230;, I&#8217;ve been writing this blog for over 9 months now, and I have yet to mention Mosha, although in my defence, there is a link to his <a href="http://sqlblog.com/blogs/mosha/" target="_blank">blog</a> in the links section to the right.</p>
<p>As many/most of you may know, Mosha Pasumansky is one the key brains behind designing the MDX language and Analysis Services &#8211; nuff said?</p>
<p>Over the last year he has been working on a pet project, MDX Studio. It&#8217;s an MDX query tool which any self respecting OLAP developer should now be using on a regular basis. He has just released v0.4.6, which adds some really nifty features such as the dependency view.</p>
<p>If you&#8217;re just starting out with MDX, then the intellisense will be of massive benefit to you; even if you&#8217;re a seasoned pro, the performance monitoring is an essential tool on its own.</p>
<p>If you haven&#8217;t already tried it, have a look at <a href="http://sqlblog.com/blogs/mosha/archive/2008/09/07/inspecting-calculation-dependencies-with-mdx-studio.aspx" target="_blank">Mosha&#8217;s blog</a>, and get a copy &#8211; you won&#8217;t regret it.</p>
<p>And thanks for all your hard work Mosha &#8211; It&#8217;s much appreciated.</p>
<p>Alex</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2008/09/moshas-mdx-studio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ranking results from MDX queries</title>
		<link>http://www.purplefrogsystems.com/blog/2008/05/ranking-results-from-mdx-queries/</link>
		<comments>http://www.purplefrogsystems.com/blog/2008/05/ranking-results-from-mdx-queries/#comments</comments>
		<pubDate>Wed, 21 May 2008 20:36:08 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[Ranking]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=14</guid>
		<description><![CDATA[This post explains how you can create a ranking of data from an OLAP MDX query. This will take the results from the query, and assign a ranking to each row. i.e. 1st, 2nd, 3rd best rows etc. The first thing to do is to decide two things. 1) What measure do you want to [...]]]></description>
			<content:encoded><![CDATA[<p>This post explains how you can create a ranking of data from an OLAP MDX query. This will take the results from the query, and assign a ranking to each row. i.e. 1st, 2nd, 3rd best rows etc.</p>
<p>The first thing to do is to decide two things.<br />
1) What measure do you want to rank by<br />
2) What data set are you returning</p>
<p>Let&#8217;s assume we want to rank all stores by sales value. The basic non-ranked MDX query would be something like this</p>
<pre><span style="color: #008000;">  SELECT
    {[Measures].[Sales Value]} ON 0,
    {[Store].[Store Name].members} ON 1
  FROM
    [SalesCube]
</span></pre>
<p>So our measure is Sales Value, and our data set (granularity) is Store Name. We now want to create an ordered set of this data, ordered by Sales Value. We do this with the ORDER() function, which takes a set, a measure and either ascending or descending as its parameters. Note that by specifying the attribute twice we remove the [All] member from the set.</p>
<pre><span style="color: #008000;">  WITH SET [OrderedSet] AS
    ORDER([Store].[Store Name].[Store Name].MEMBERS,
	  [Measures].[Sales Value],
	  BDESC)
  SELECT
    {[Measures].[Sales Value]} ON 0,
    {[OrderedSet]} ON 1
  FROM
    [SalesCube]
</span></pre>
<p>The next stage is to apply a ranking to this ordered set. Helpfully, MDX provides us with a Rank() function, which takes a member and a set as its parameters. All it does is locate the member within the set and return its position. Because we have ordered the set, it will give us the ranking.</p>
<pre><span style="color: #008000;">  WITH SET [OrderedSet] AS
    ORDER([Store].[Store Name].[Store Name].MEMBERS,
	  [Measures].[Sales Value],
	  BDESC)
  MEMBER [Measures].[Rank] AS
    RANK([Store].[Store Name].CurrentMember,
	 [OrderedSet])
  SELECT
    {[Measures].[Rank], [Measures].[Sales Value]} ON 0,
    {[OrderedSet]} ON 1
  FROM
    [SalesCube]
</span></pre>
<p>You can now easily expand this to only show you the top x records, by using the Head() function on the ordered set. In this example we&#8217;re only showing the top 10. You could also use Tail() to find the bottom x records. Other functions you can use include TopPercent(), TopSum(), BottomPercent() and BottomSum().</p>
<pre><span style="color: #008000;">  WITH SET [OrderedSet] AS
    ORDER([Store].[Store Name].[Store Name].MEMBERS,
	  [Measures].[Sales Value],
	  BDESC)
  MEMBER [Measures].[Rank] AS
    RANK([Store].[Store Name].CurrentMember,
	 [OrderedSet])
  SELECT
    {[Measures].[Rank], [Measures].[Sales Value]} ON 0,
    {HEAD([OrderedSet], 10)} ON 1
  FROM
    [SalesCube]
</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2008/05/ranking-results-from-mdx-queries/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Semi Additive Measures using SQL Server Standard</title>
		<link>http://www.purplefrogsystems.com/blog/2008/04/semi-additive-measures-using-sql-server-standard/</link>
		<comments>http://www.purplefrogsystems.com/blog/2008/04/semi-additive-measures-using-sql-server-standard/#comments</comments>
		<pubDate>Mon, 21 Apr 2008 12:54:36 +0000</pubDate>
		<dc:creator>Alex</dc:creator>
				<category><![CDATA[Analysis Services]]></category>
		<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[Cube]]></category>
		<category><![CDATA[MDX]]></category>
		<category><![CDATA[OLAP]]></category>
		<category><![CDATA[Semi Additive]]></category>

		<guid isPermaLink="false">http://www.purplefrogsystems.com/blog/?p=12</guid>
		<description><![CDATA[One of the most frustrating limitations of SQL Server 2005 Standard edition is that it doesn&#8217;t support semi additive measures in SSAS Analysis Services cubes. This post explains a work around that provides similar functionality without having to shell out for the Enterprise Edition. What Are Semi Additive Measures? Semi Additive measures are values that [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most frustrating limitations of SQL Server 2005 Standard edition is that it doesn&#8217;t support semi additive measures in SSAS Analysis Services cubes. This post explains a work around that provides similar functionality without having to shell out for the Enterprise Edition.</p>
<p><strong>What Are Semi Additive Measures?</strong></p>
<p>Semi Additive measures are values that you can summarise across any related dimension except time.</p>
<p>For example, Sales and costs are fully additive; if you sell 100 yesterday and 50 today then you&#8217;ve sold 150 in total. You can add them up over time.</p>
<p>Stock levels however are semi additive; if you had 100 in stock yesterday, and 50 in stock today, you&#8217;re total stock is 50, not 150. It doesn&#8217;t make sense to add up the measures over time, you need to find the most recent value.</p>
<p><strong>Why are they important?</strong></p>
<p>Whether they are important to you or not depends entirely on what you are trying to do with your cube. If all of your required measures are fully additive then you really don&#8217;t need to worry about anything. However as soon as you want to include measures such as stock levels, salarys, share prices or test results then they become pretty much essential.</p>
<p><strong>Why are they not available in SQL Standard edition?</strong></p>
<p>Microsoft has to have some way of pursuading us to pay for the Enterprise edition!</p>
<p><strong>How can I get this functionality within SQL Standard?</strong></p>
<p>Firstly we need to understand what semi additive measures do. By far the most common aggregation used is the LastNonEmpty function, so we&#8217;ll stick with that as an example. This basically says that whatever time frame you are looking at, find the most recent value for each tuple. This really is a fantastically powerful function, which only really becomes apparent whan you don&#8217;t have it!</p>
<p>Lets say that you perform a stock take of different products on different days of the week. You will have a stock entry for product A on a Thursday and product B on a Friday. The LastNonEmpty function takes care of this for you, if you look at the stock level on Saturday it will give you the correct values for both A and B, even though you didn&#8217;t perform a physical stock take on the Saturday.</p>
<p>If you then add the time dimension into the query, SSAS will perform this function for each and every time attribute shown, and then aggregate the results up to any other dimensions used. i.e. Each month will then display the sum of all LastNonEmpty values for all products within that month, essentially the closing stock level for each and every month.</p>
<p>To replicate this in Standard Edition, we need to split the work up into two stages.<br />
1) Create daily values in the data warehouse<br />
2) Use MDX to select a single value from the time dimension.</p>
<p>Think of this as splitting up the LastNonEmpty function into two, &#8216;Last&#8217; and &#8216;Non Empty&#8217;. The &#8216;Non Empty&#8217; bit essentially fills in the blanks for us. If a value doesn&#8217;t exist for that particular day, it looks at the previous day&#8217;s value. The &#8216;Last&#8217; bit says that if we are looking at months in our query, find the value for the last day in that month. The same goes for years, or indeed any other time attribute.</p>
<p>To code up a full LastNonEmpty function ourselves in MDX would be too slow to query as soon as you get a cube of any reasonable size. One of the key benefits of a cube is speed of querying data and we don&#8217;t want to impact this too much, therefore we move some of the donkey work into the ETL process populating the datawarehouse. This leaves the cube to perform a simple enough calculation so as to not cause any problems.</p>
<p><strong>1) The &#8216;Non Empty&#8217; bit</strong></p>
<p>Lets say that have a table called tblStock, containing the following data</p>
<p style="text-align: center;"><img src="http://www.purplefrogsystems.com/images/blog/tblStock.png" alt="" /></p>
<p>We need to expand this into a new fact table that contains one record per day per product.</p>
<p style="text-align: center;"><img src="http://www.purplefrogsystems.com/images/blog/FactStock.png" alt="" /></p>
<p>There are a number of ways of doing this, I&#8217;ll describe one here that should suit most situations, although you may need to customise it to your own situation, and limit it to only updating changed/new records rather than re-populating the entire table, but you get the idea. I should point out that you would be much better off populating this as part of your ETL process, but I&#8217;m showing this method as it&#8217;s more generic.</p>
<p>You need a list of all available dates relevant to your data warehouse or cube. If you already have a time dimension table then use this, otherwise create a SQL function that returns you a list of dates, such as this one:</p>
<pre><span style="color: #008000;">
   CREATE FUNCTION [dbo].[FN_ReturnAllDates](
         @DateFrom DateTime, @DateTo DateTime)
         RETURNS @List TABLE (Date DateTime)
     BEGIN
     DECLARE @tmpDate DateTime
     SET @tmpDate = @DateFrom
     WHILE @tmpDate&lt;=@DateTo
       BEGIN
         INSERT INTO @List
           SELECT Convert(datetime,
                 Convert(Nvarchar,@tmpDate, 102), 102)
         SET @tmpDate = Dateadd(d,1,@tmpDate)
       END
     RETURN
   END
</span></pre>
<p>We need to perform a full outer join between the date dimension and any other relevant dimensions, in this case product. This will generate one record per product per date. We can then perform a sub query for each combination to find the stock level appropriate for that day. (Yes, this will be a slow query to run &#8211; I did say you should do it in your ETL process!)</p>
<pre><span style="color: #008000;">
     INSERT INTO FactStock
        (StockTakeDate, ProductID, StockLevel)
     SELECT D.Date, P.ProductID,
           ISNULL((SELECT TOP 1 StockLevel
              FROM tblStock
              WHERE ProductID = P.ProductID
                 AND StockTakeDate&lt;=D.Date
              ORDER BY StockTakeDate DESC),0)
        FROM FN_ReturnAllDates((SELECT Min(StockTakeDate)
                      FROM tblStock),GetDate()) D
           FULL OUTER JOIN
                    (SELECT ProductID FROM tblProduct) P ON 1=1
</span></pre>
<p><strong>2) The &#8216;Last&#8217; bit</strong></p>
<p>Now that we have a large fact table consisting of one record per product/date, we can load this into the cube.</p>
<p>If you just add the StockLevel field as a measure and browse the results, you&#8217;ll quickly see that if you view it by month, you will get each day&#8217;s stock level added together giving you a non-sensical value. To fix this we need to tell Analysis Services to only show one day&#8217;s value.</p>
<p>To do this we first need to find all descendents of the current time member at the day level, using something like this:</p>
<pre><span style="color: #008000;">     DESCENDANTS([Time].[Year Month Day].CurrentMember,
       [Time].[Year Month Day].[Day])
       --Please modify to suit your own date hierarchy! </span></pre>
<p>We can then find the last member (giving us the closing stock level) by using TAIL():</p>
<pre><span style="color: #008000;">     TAIL(DESCENDANTS([Time].[Year Month Day].CurrentMember,
          [Time].[Year Month Day].[Day]))</span></pre>
<p>You could aso use HEAD() if you wanted to find the opening stock instead of closing.</p>
<p>You should hide the actual StockLevel measure to prevent users from selecting it, I usually alias these with an underscore, as well as making them invisible, just for clarity. You can then add a calculated member with the following MDX:</p>
<pre><span style="color: #008000;">
     CREATE MEMBER CURRENTCUBE.[MEASURES].[Stock Level Close]
      AS SUM(TAIL(DESCENDANTS([Time].[Year Month Day].currentmember,
                    [Time].[Year Month Day].[Day])),
                    [Measures].[_Stock Level]),
     FORMAT_STRING = "#,#",
     VISIBLE = 1  ;
</span></pre>
<p>Or you can calculate the average stock over the selected period</p>
<pre><span style="color: #008000;">
     CREATE MEMBER CURRENTCUBE.[MEASURES].[Stock Level Avg]
      AS AVG(DESCENDANTS([Time].[Year Month Day].currentmember,
                   [Time].[Year Month Day].[Day]),
                   [Measures].[_Stock Level]),
     FORMAT_STRING = "#,#",
     VISIBLE = 1  ;
</span></pre>
<p>Or the maximum value</p>
<pre><span style="color: #008000;">
     CREATE MEMBER CURRENTCUBE.[MEASURES].[Stock Level Max]
      AS MAX(DESCENDANTS([Time].[Year Month Day].currentmember,
                   [Time].[Year Month Day].[Day]),
                   [Measures].[_Stock Level]),
     FORMAT_STRING = "#,#",
     VISIBLE = 1  ;
</span></pre>
<p>Or the mimimum value</p>
<pre><span style="color: #008000;">
     CREATE MEMBER CURRENTCUBE.[MEASURES].[Stock Level Min]
      AS MIN(DESCENDANTS([Time].[Year Month Day].currentmember,
                  [Time].[Year Month Day].[Day]),
                  [Measures].[_Stock Level]),
     FORMAT_STRING = "#,#",
     VISIBLE = 1  ;
</span></pre>
<p>And there you have it, <strong><span>semi additive measures in SQL Server 2005 Standard Edition!</span></strong></p>
<p>Even though this method does work well, it is still not as good as having the Enterprise edition. The built in functions of Enterprise will perform significantly better than this method, and it saves having to create the large (potentially huge) fact table. This process will also only work on a single date hierarchy. If you have multiple hierarchies (i.e. fiscal and calendar) you will need to enhance this somewhat.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purplefrogsystems.com/blog/2008/04/semi-additive-measures-using-sql-server-standard/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

