Search code examples
ssasmdx

"Same Store" calculations with MDX


I am new to MDX and can't find this on google.

I am trying to get an average price over time for a consistent set of records (excluding any records added, or removed in the period).

I have tried a few approaches but keep hitting a wall, this is my latest attempt which results in "#Error Infinite recursion detected. The loop of dependencies is: Avg Monthly Price (Same Store) -> Avg Monthly Price (Same Store)."

WITH
// Period Data
    MEMBER [Date].[Date Id].PeriodCount AS
        COUNT([Date].[Period].&[2018-01-01T00:00:00] : [Date].[Period].&[2018-12-01T00:00:00])
    MEMBER [Date].[Date Id].NonEmptyPeriodCount AS
        COUNT(
            NonEmpty(
                [Date].[Period].&[2018-01-01T00:00:00] : [Date].[Period].&[2018-12-01T00:00:00],
                [Measures].[Monthly Price]
            )
        )

// Calculations
    MEMBER Measures.[Avg Monthly Price] AS [Measures].[Monthly Price] / [Measures].[Fact Monthly Price History Count]
    MEMBER Measures.[Avg Monthly Price (Same Store)] AS 
        AGGREGATE(
            FILTER(
                [Product].[Product Id].MEMBERS,
                [Date].[Date Id].NonEmptyPeriodCount = [Date].[Date Id].PeriodCount
            ),
            [Measures].[Monthly Price] 
        )
SELECT
    NON EMPTY {
        [Measures].[Avg Monthly Price],
        [Measures].[Avg Monthly Price (Same Store)]
    } ON COLUMNS,
    NON EMPTY (
        [Date].[Period].Children
    ) ON ROWS
FROM
    MyCube
WHERE
    [Date].[Year].&[2018]

I feel like this should be much easier than I am making it... Any help would be really appreciated.


Edit:

The problem I am trying to solve in simple terms Is to get the average value per date, excluding any records that were added or removed during the overall reporting period.

For example given the following set:

Record | 1/1/2019 | 2/1/2019 | 3/1/2019 | 4/1/2019 | 5/1/2019
1      | 9        | 10       | 11       | 12       | 13
2      |          |          | 22       | 23       | 24
3      | 10       | 11       | 12       | 13       | 14
4      | 20       | 21       | 22       |          |
5      | 11       | 12       | 13       | 14       | 15

I would want to exclude records 2 and 4 since they don't exist throughout the set so the avg overtime would be effected by records being added or removed.

For the above set I would want to return:

Period   | Avg.
1/1/2019 | 10
2/1/2019 | 11
3/1/2019 | 12
4/1/2019 | 13
5/1/2019 | 14

Solution

  • I was able to get this working by adding a Period Count measure into the cube, and then using aggregate members, my final result looked like this:

    WITH
        MEMBER [Date].[Hierarchy].Dates AS
            AGGREGATE({
                [Date].[Hierarchy].[Period].&[2018-01-01T00:00:00], 
                [Date].[Hierarchy].[Period].&[2018-02-01T00:00:00], 
                [Date].[Hierarchy].[Period].&[2018-03-01T00:00:00], 
                [Date].[Hierarchy].[Period].&[2018-04-01T00:00:00], 
                [Date].[Hierarchy].[Period].&[2018-05-01T00:00:00], 
                [Date].[Hierarchy].[Period].&[2018-06-01T00:00:00]
            })
        MEMBER AvgMonthlyPrice AS
            [Measures].[Monthly Price] / [Measures].[Monthly Price Count]
        MEMBER [Location].[Location Id].ValidLocation AS
            AGGREGATE(FILTER(EXISTING([Location].[Location Id].[Location Id]), ([Measures].[Period Count], [Date].[Hierarchy].Dates) = 6))
    SELECT
        {[Measures].[Monthly Price],[Measures].[Monthly Price Count], AvgMonthlyPrice, [Property Count]} ON COLUMNS,
        [Date].[Period].[Period] ON ROWS
    FROM
        [MyCube]
    WHERE
        (
            [Date].[Hierarchy].Dates,
            [Market].[Market Id].&[300000],
            [Location].[Location Id].ValidLocation
        )
    

    There is likely a more elegant way of doing this but this works for now.