MDX equivalent of a filtered GROUP BY in SQL

Does that title make sense? I don't know if it does, but I can't think of another description for this problem. If anyone can think of a better title I would love to hear it. It's hard to explain in words so let's jump into some code examples.

Consider the following SQL statement against the AdventureWorksDW relational database. The requirement is to select a list of 4 cities and then want to see the order quantity grouped at the country level.

SELECT g.EnglishCountryRegionName Country ,sum(OrderQuantity) as OrderQuantity FROM dbo.FactResellerSales rs INNER JOIN dimReseller r ON r.ResellerKey = rs.ResellerKey INNER JOIN dimGeography g ON g.GeographyKey = r.GeographyKey WHERE g.City IN ('Melbourne','Sydney','Seattle','New York') GROUP BY g.EnglishCountryRegionName

This query returns the following result:

image

How can we do an equivalent query in MDX?

if you start with something like the following it gets you the correct raw figures, but it breaks the amounts out for each city and we want to see the sub-totals by country.

SELECT [Measures].[Reseller Order Quantity] on 0 ,{[Geography].[City].[Melbourne] ,[Geography].[City].[Sydney] ,[Geography].[City].[Seattle] ,[Geography].[City].[New York]} on 1 FROM [Adventure Works]

This is the result that you get:

image

So then you might figure that putting the country members on the axis and the cities in the where clause should do the trick.

SELECT {Measures.[Reseller Order Quantity]} on 0 ,[Geography].[Country].[Country].Members on 1 FROM [Adventure Works] WHERE ( {[Geography].[City].[Melbourne] ,[Geography].[City].[Sydney] ,[Geography].[City].[Seattle] ,[Geography].[City].[New York]})

But then we get the following...

image

So what is going on here? The query has returned the total amounts for the entire countries, not just the sub totals for the cities in the WHERE clause. Because of the attribute relationship between Countries and Cities, SSAS has put the country members on the rows that are related to the cities in the WHERE clause. In effect what this query is roughly saying to SSAS is "show me the Reseller Order Quantity for the Countries that contain one or more of the following cities. There is a more in depth explanation of this behavior here: Attribute Relationships Explained

So what we want to do is to get a measure that is filtered to figures for the selected cities. One way of doing this would be to created a calculated measure like the following:

WITH MEMBER Measures.FilteredSales as SUM( EXISTING {[Geography].[City].[Melbourne] ,[Geography].[City].[Sydney] ,[Geography].[City].[Seattle] ,[Geography].[City].[New York]} , [Measures].[Reseller Order Quantity]) SELECT {Measures.[FilteredSales]} on 0 ,[Geography].[Country].[Country].Members on 1 FROM [Adventure Works] WHERE ( {[Geography].[City].[Melbourne] ,[Geography].[City].[Sydney] ,[Geography].[City].[Seattle] ,[Geography].[City].[New York]})

This gets the result that we are after, but it was a rather convoluted solution**.**

image

However, there is an easier way. We could use a sub-select...

SELECT [Measures].[Reseller Order Quantity] on 0, [Geography].[Country].[Country].Members on 1 FROM (
SELECT {[Geography].[City].[Melbourne] ,[Geography].[City].[Sydney] ,[Geography].[City].[Seattle] ,[Geography].[City].[New York]} on 0 FROM [Adventure Works] )

Which returns the following:

image

Which is exactly what we were after. I usually tend to avoid using sub-selects when I can as I don't like how they can affect calculated measures because the sub-select is not visible to functions like .CurrentMember. But there are situations like this, where they are perfectly suited and are much simpler than an alternative solution.

This article is part of the GWB Archives. Original Author: Darren Gosbell

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.