PY YTD рассчитанная мера, которая может обрабатывать високосные годы MDX - PullRequest
1 голос
/ 25 марта 2020

Это может быть длинный пример, но, возможно, здесь есть гуру ssas / mdx, который столкнулся с той же проблемой, касающейся агрегированных вычислений и високосных лет. Поэтому я пытаюсь создать вычисленную меру PY YTD в кубе ssas, который может обрабатывать високосные годы. Проблема, с которой я сталкиваюсь, заключается в том, что вычисленная мера становится чрезвычайно медленной на основе логики c ниже (см. Пример кода). Кто-нибудь нашел лучший способ справиться с високосными годами или есть документ с передовой практикой, чтобы поделиться? Я предполагаю, что операторы if и функция NonEmpty могут быть смертельно опасными для вычисляемой меры. Все советы приветствуются (не должно быть решением).

-- 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)))

    )
    )
    )
    )
);

С уважением, Рубрикс

1 Ответ

1 голос
/ 15 апреля 2020

Попробуйте следующее, некоторые предостережения следуют:

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;

Одна из возможных проблем заключается в том, что если у вас есть несколько дней подряд, когда нет транзакций, .LastChild может работать некорректно. У меня не было той ситуации, когда я изначально разрабатывал этот код. Он был специально разработан для того, чтобы разобраться с этим конкретным случаем прошлых нюансов и нюансов високосного года. В этом случае, возможно, потребуется настроить его.

Это предполагает, что у вас есть правильное измерение времени и измерение вычислений времени, что похоже на то, что вы делаете из предоставленного вами примера кода.

Я бы сказал, что производительность этого решения довольно велика даже на больших кубах (сотни миллионов строк).

...