tags:

views:

460

answers:

1

I have a situation where I have a product and a time dimension, with a fact table of sales volume. Over time, various details about the product changes, with the except of the business key for the product. In my flat reporting from the cube, I want to include some aggregration at the 'business key' level, regardless of what other parts of the product dimension are shown.

In sql this would be trivial as something like:

select sum(volume) over (partition by productKey,year) as Total

Regardless of whatever else I had selected, the Total column would be aggregated only on those two fields.

In MDX I have managed to achieve the same result, but it seems like there must be a simpler way.

WITH MEMBER Measures.ProductKeyTotal AS
  'SUM(([Product].[ProductKey],[Time].[Year]
       ,[Product].[Product Name].[Product Name].ALLMEMBERS
       ,[Volume Type].[Volume Type Id].[Volume Type Id].ALLMEMBERS)
       ,[Measures].[Volume])'
SELECT {[Measures].[Volume],[Measures].[ProductKeyTotal]} ON COLUMNS,
    NONEMPTYCROSSJOIN ([Product].[ProductKey].[ProductKey].ALLMEMBERS
      ,[Time].[Time].[Year].ALLMEMBERS
      ,[Product].[Product Name].[Product Name].ALLMEMBERS
      ,[Volume Type].[Volume Type Id].[Volume Type Id].ALLMEMBERS) ON ROWS
FROM [My Cube]
WHERE ([Product].[Include In Report].&[True])

1) If I don't include the allmembers for the rows I don't want in the calculated member the total is not correct, is there a shortcut to force it to ignore all the dimensions other that what you specify?

Part of the reason I ask is that I need to add a bunch of other calculated members, some of which will be using parameters and if I use the method from the example above I am going to need to duplicate the same stuff in multiple places, and the code will get weighty.

+1  A: 

Well, first of all, don't use NonEmptyCrossJoin--it's been deprecated. Use non empty and then the cross join operator (*).

It's important to understand how tuples and tuple sets work to answer your question. Essentially, any dimension not explicitly stated will always get the CurrentMember of a given dimension. Typically, this is DefaultMember, but if you have it set to something else in your query, that will change this up. The reason you have to specify ALLMEMBERS for those dimensions is because it will use CurrentMember, otherwise. You could just use the [All] member in lieu of trying to sum up ALLMEMBERS (especially if they're not flat!), which will give you a bit better performance.

The most performant way to do this is to add another Measure Group to your cube, and then remove the keys that don't apply to the measure from that Measure Group. This way, you get a native calculation for these rather than a run-time calculation (which tend to be slow, especially when you're adding up everything in your cube). Moreover, you can even set up some aggregation design on that Measure Group, and it will be very performant.

Eric
I was using NonEmptyCrossJoin because reporting services would explode with the too many tuples error when I brought in too many dimensions. It seemed to fix that problem.The problem with adding another measure group is that it won't let me use the fact table I am already using for the more granular aggregate. I will try to add another 'table' based on a query of my fact table, but it might be tricky because I need to aggregate over the business key and the year and nothing else.
Peter