ssasmdx

Using accumulative sum on ordered MDX query


I have an MDX query That is sorted and I want to add an accumulative sum column.

The problem is that when I use an aggregate function, it still sum the values in default order, not the order I specified. below is my MDX query:

WITH 
  MEMBER RunningTotal AS 
    Aggregate
    (
      {
          [Dim Product].[ProductName].FirstChild
        : 
          [Dim Product].[ProductName].CurrentMember
      }
     ,[Measures].[Sales Amount]
    ) 
SELECT 
  {
    [Measures].[Sales Amount]
   ,RunningTotal
  } ON 0
 ,NonEmpty
  (
    Order
    (
      [Dim Product].[ProductName].[ProductName]
     ,[Measures].[Sales Amount]
     ,Desc
    )
  ) ON 1
FROM [InternetSales];

Solution

  • This is your query - you mention a 'specified order' but I cannot see one:

    WITH 
      MEMBER RunningTotal AS 
        Aggregate
        (
          {
              [Dim Product].[ProductName].FirstChild
            : 
              [Dim Product].[ProductName].CurrentMember
          }
         ,[Measures].[Sales Amount]
        ) 
    SELECT 
      {
        [Measures].[Sales Amount]
       ,RunningTotal
      } ON COLUMNS
     ,NON EMPTY 
        [Dim Product].[ProductName].[ProductName] ON ROWS
    FROM [InternetSales];
    

    As an example I think if you'd like to order the rows by Sales Amount then you could introduce an ORDER function:

    WITH 
      MEMBER RunningTotal AS 
        Aggregate
        (
          {
              [Dim Product].[ProductName].FirstChild
            : 
              [Dim Product].[ProductName].CurrentMember
          }
         ,[Measures].[Sales Amount]
        ) 
    SELECT 
      {
        [Measures].[Sales Amount]
       ,RunningTotal
      } ON 0
     ,NON EMPTY 
        Order
        (
          [Dim Product].[ProductName].[ProductName]
         ,[Measures].[Sales Amount]
         ,BDESC
        ) ON 1
    FROM [InternetSales];
    

    Example against AdvWrks:

    WITH 
      MEMBER RunningTotal AS 
        Aggregate
        (
          {
              [Product].[Category].FirstChild
            : 
              [Product].[Category].CurrentMember
          }
         ,[Measures].[Sales Amount]
        ) 
    SELECT 
      {
        [Measures].[Sales Amount]
       ,RunningTotal
      } ON 0
     ,NON EMPTY 
        Order
        (
          [Product].[Category].[Category]
         ,[Measures].[RunningTotal]
         ,BASC
        ) ON 1
    FROM [Adventure Works]
    

    Returns the following:

    enter image description here


    An alternative that gets around the ordering inherited from the cube is the following:

    WITH 
      SET X_UNORDERED AS 
        {
          NonEmpty
          (
            {[Product].[Category].[Category].MEMBERS}
           ,[Measures].[Sales Amount]
          )
        } 
      SET X_ORDERED AS 
        {Order(X_UNORDERED,[Measures].[Sales Amount])} 
      MEMBER [Measures].[Rank] AS 
        Rank
        (
          [Product].[Category].CurrentMember
         ,X_ORDERED
        ) 
      MEMBER [Measures].[RunningSum] AS 
        IIF
        (
          [Measures].[Rank] = 1
         ,[Measures].[Sales Amount]
         ,
            [Measures].[Sales Amount]
          + 
            (
              [Measures].[RunningSum]
             ,X_ORDERED.Item(
              [Measures].[Rank] - 2)
            )
        ), FORMAT_STRING="$#,#.00"
    SELECT 
      {
        [Measures].[Sales Amount]
       ,[Measures].[RunningSum]
      } ON 0
     ,X_ORDERED ON 1
    FROM [Adventure Works];
    

    Returns the values in the order you want:

    enter image description here