I had a little challenge back in work and I solved it (in a couple of hours). Here is the description of the problem and its solution:
Let's say that I have a Products dimension, time dimension and a fact table that describes all the faults which occurred in these products. The new requirement is that: Given a product-tree that describes all the parts of every product, I want to know how many faults occurred to every part. The problem is that the fact table points only to the products and the customer wants to know how many faults happened to the parts.
The two solutions I thought about are:
1. The trivial solution: Build a view above the fact table that takes every row and adds a row for each of its product's parts. That way, the fact will contain every fault that happened to every part. The problem with this solution is that the view is very long to compute.
2. The good solution: Build a parent-child dimension out of the parts table which will describe all the parts of every product. Notice that this dimension is not ragged, meaning that one member can have 2 children while another member in the same level can have 10 children. The next step is to add this MDX Script:
Calculate;
Scope([Measures].[Faults],
Descendants([Products].[Products].[All],
1,
After));
This = Ancestor([Products].[Products].CurrentMember,
[Products].[Products].[Level 02]);
End Scope;
Scope([Measures].[Faults],
[Products].[Products].[Level 02].Members);
This = ([Products].[Products].CurrentMember)
-
Sum([Products].[Products].CurrentMember.Children);
End Scope;
Explanation: The first level of the dimension is the [All] member. The second level is the products and the other levels contain the parts. The first block takes all the parts and inherits their amount of faults from their product ancestor. The second block solves the aggregation problem: Let's say that The bike product has 3 children. The bike had 4 faults in our slice of time, so according to the first block of the script every child has 4 faults. Now, the cube makes its aggregation and now the bikes has 16 faults - 4 of its own and more 4 for every of its parts. The second block decreases the sum of the product's children from the products and the result is that the products have their original number of faults.