How do I define a Calculated Measure in MDX based on a Dimension Attribute?

Shane Delmore picture Shane Delmore · Apr 16, 2010 · Viewed 13.6k times · Source

I would like to create a calculated measure that sums up only a specific subset of records in my fact table based on a dimension attribute.

Given:

Dimension

  • Date
  • LedgerLineItem {Charge, Payment, Write-Off, Copay, Credit}

Measures

  • LedgerAmount

Relationships
* LedgerLineItem is a degenerate dimension of FactLedger

If I break down LedgerAmount by LedgerLineItem.Type I can easily see how much is charged, paid, credit, etc, but when I do not break it down by LedgerLineItem.Type I cannot easily add the credit, paid, credit, etc into a pivot table. I would like to create separate calculated measures that sum only specific type (or multiple types) of ledger facts.

An example of the desired output would be:

| Year  | Charged | Total Paid | Amount - Ledger |
| 2008  | $1000   | $600       | -$400           |
| 2009  | $2000   | $1500      | -$500           |
| Total | $3000   | $2100      | -$900           |

I have tried to create the calculated measure a couple of ways and each one works in some circumstances but not in others. Now before anyone says do this in ETL, I have already done it in ETL and it works just fine. What I am trying to do as part of learning to understand MDX better is to figure out how to duplicate what I have done in the ETL in MDX as so far I am unable to do that.

Here are two attempts I have made and the problems with them. This works only when ledger type is in the pivot table. It returns the correct amount of the ledger entries (although in this case it is identical to [amount - ledger] but when I try to remove type and just get the sum of all ledger entries it returns unknown.

CREATE MEMBER CURRENTCUBE.[Measures].[Received Payment]
AS CASE WHEN ([Ledger].[Type].currentMember = [Ledger].[Type].&[Credit]) 
OR ([Ledger].[Type].currentMember = [Ledger].[Type].&[Paid])
OR ([Ledger].[Type].currentMember = [Ledger].[Type].&[Held Money: Copay])
THEN [Measures].[Amount - ledger] 
ELSE 0
END 
, FORMAT_STRING = "Currency"
, VISIBLE = 1 
, ASSOCIATED_MEASURE_GROUP = 'Ledger'  ; 

This works only when ledger type is not in the pivot table. It always returns the total payment amount, which is incorrect when I am slicing by type as I would only expect to see the credit portion under credit, the paid portion, under paid, $0 under charge, etc.

CREATE MEMBER CURRENTCUBE.[Measures].[Received Payment]
AS sum({([Ledger].[Type].&[Credit]), ([Ledger].[Type].&[Paid])
, ([Ledger].[Type].&[Held Money: Copay])}
,  [Measures].[Amount - Ledger])
, FORMAT_STRING = "Currency"
, VISIBLE = 1 
, ASSOCIATED_MEASURE_GROUP = 'Ledger'  ;  

Is there any way to make this return the correct numbers regardless of whether Ledger.Type is included in my pivot table or not?

Answer

Meff picture Meff · Apr 20, 2010

Try EXISTING:

CREATE MEMBER CURRENTCUBE.[Measures].[Received Payment]
AS sum(Existing({([Ledger].[Type].&[Credit]), ([Ledger].[Type].&[Paid])
, ([Ledger].[Type].&[Held Money: Copay])})
,  [Measures].[Amount - Ledger])
, FORMAT_STRING = "Currency"
, VISIBLE = 1 
, ASSOCIATED_MEASURE_GROUP = 'Ledger'  ;  

Should make it pay attention to the members in play.