简体   繁体   中英

PY YTD calculated measure that can handle leap years MDX

This might be a longshot, but maybe there is an ssas/mdx guru here that has stumpled upon the same problem regarding aggregated calculations and leap years. So what I am trying to do, is to create a PY YTD calculated measure in an ssas cube that can handle leap years. The issue I am facing is that the calculated measure becomes extremely slow based on the logic below (see code sample). Has anyone found a better way to handle leap years or has a document with best practise to share ? I am assume that if-statements and NonEmpty function could be performance deadly for a calculated measure. All tips are greatly appreciated (Doesn't have to be a solution).

-- YTD PRIOR YEAR
[Time Calculations].[YTD Pr Yr] = IIF([Calendar].[Year - Month - Day].CurrentMember IS [Calendar].[Year - Month - Day].[Month].&[201702]
,Aggregate(
    NonEmptyCrossjoin({[Time Calculations].[Current Period]},
    PeriodsToDate(
        [Calendar].[Year - Month - Day].[Year],
[Calendar].[Year - Month - Day].[Day].&[2016-02-29 00:00:00.000])
))
,IIF([Calendar].[Year - Month - Day].CurrentMember IS [Calendar].[Year - Month - Day].[Month].&[201602]
,Aggregate(
    NonEmptyCrossjoin({[Time Calculations].[Current Period]},
    PeriodsToDate(
        [Calendar].[Year - Month - Day].[Year],
[Calendar].[Year - Month - Day].[Day].&[2015-02-28 00:00:00.000])
))
,(Aggregate(
    NonEmptyCrossjoin({[Time Calculations].[Current Period]},
    PeriodsToDate(
        [Calendar].[Year - Month - Day].[Year],
        ParallelPeriod(
           [Calendar].[Year - Month - Day].[Year],1,

TAIL(DESCENDANTS([Calendar].[Year - Month - Day].CurrentMember
, [Calendar].[Year - Month - Day].[Day]),1).ITEM(0)))

    )
    )
    )
    )
);

Best regards, Rubrix

Try the following, some caveats follow:

CREATE MEMBER CURRENTCUBE.[Time Calculations].[YTD Prior Year] AS NULL; 

/* Make sure the scope is for all days in all years in your calendar year */
Scope([Invoice Date].[Calendar Year].[Calendar Year].members, [Invoice Date].[Calendar Day].members); 

    // YTD PRIOR YEAR
    ([Time Calculations].[YTD Prior Year] =
        iif(
            /* Check to see if the prior year member is empty */
            isempty(
                ParallelPeriod(
                    [Invoice Date].[CY Hierarchy].[Calendar Year],
                    1,
                    [Invoice Date].[CY Hierarchy].CurrentMember
                ).MemberValue
            ),
            /* If so, use the .LastChild */
            Aggregate(
                Crossjoin(
                    {[Time Calculations].[Current Period]},
                    PeriodsToDate(
                        [Invoice Date].[CY Hierarchy].[Calendar Year],
                        ParallelPeriod(
                            [Invoice Date].[CY Hierarchy].[Calendar Year],
                            1,
                            Ancestor(
                                [Invoice Date].[CY Hierarchy].CurrentMember,
                                [Invoice Date].[CY Hierarchy].[Calendar Month]
                            )
                        ).LastChild
                    )
                )
            ),
            /* Otherwise just use the prior year */
            Aggregate(
                Crossjoin(
                    {[Time Calculations].[Current Period]},
                    PeriodsToDate(
                        [Invoice Date].[CY Hierarchy].[Calendar Year],
                        ParallelPeriod(
                            [Invoice Date].[CY Hierarchy].[Calendar Year],
                            1,
                            [Invoice Date].[CY Hierarchy].CurrentMember
                        )
                    )
                )
            )
        )
    ); 

End Scope;

One possible hitch is that if you have several days in a row where there are no transactions, .LastChild might not work accurately. I didn't have that situation when I originally developed this code. It was specifically developed to deal with this exact case of prior year-to-date and leap year nuances. It might need to be tweaked if that's the case.

This assumes that you have a proper time dimension and a time calculations dimension, which it looks like you do from the code sample you provided.

I would say that the performance of this solution is pretty great even on large cubes (hundreds of millions of rows).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM