Чего нужно достичь
Есть измерения [D1], [D2], [D3] и мера [M].
Каждое измерение связано с [M] как многие-ко-многим.
Мне нужно создать универсальную меру с формулой [M] / S( [M] ), где S — сумма всех фактов меры, ассоциированных хотя бы с одним членов текущего измерения (текущего = использующегося в MDX-запросе).
Что я пробовал
S( [M] ) можно задать в качестве расчётной меры, используя MDX:
CREATE HIDDEN [Total M] =
AGGREGATE(
DESCENDANTS(
AXIS( 1 ).ITEM( 0 ).DIMENSION.LEVELS( 0 ).ITEM( 0 ),
AXIS( 1 ).ITEM( 0 ).DIMENSION.LEVELS.COUNT
) - AXIS( 1 ).ITEM( 0 ).DIMENSION.LEVELS( 0 ).ITEM( 0 ),
[Measures].[M]
);
Приходится аггрегировать все члены, кроме [All], но такое решение работает.
(Если же брать общее значение [M] по всему измерению, то значение получается неверным, потому что тип связи — многие-ко-многим.)
Ипользование AXIS( 1 ), —
на самом деле, AXIS( [First Dimension Index] ), — позволяет этой расчётной мере быть универсальной и работать с любым из измерений [D1], [D2], [D3].
Теперь можно задать и меру по формуле [M] / S( [M] ):
CREATE MEMBER CURRENTCUBE.[Measures].[Share of M] AS
[Measures].[M] / [Measures].[Total M]
Однако, такая универсальность имеет и недостатки. Например, следующий запрос вернёт ошибку «бесконечная рекурсия»:
SELECT [Measures].[Share of M] ON 0,
ORDER( [D1].MEMBERS, [Measures].[Share of M] ) ON 1
FROM [MyCube]
Это, впрочем, достаточно логично, ведь, чтобы получить AXIS( 1 ).ITEM( 0 ), который мы используем в [Total M], SSAS необходимо сначала получить множество всех членов на оси 1. Но чтобы получить это множество, сначала нужно отсортировать члены [D1], используя ту же самую меру. Возникает циклическая зависимость.
Получается, что такую универсальную меру можно использовать только в самых простых запросах. А в реальных условиях она практически бесполезна.
Что делать?
Может быть, и есть способ решить задачу при помощи MDX, но у меня это не получается. Так что, если у вас есть идеи, то пожалуйста подскажите, в какую сторону двигаться.
Другое направление, которое я хочу попробовать, — написать хранимую процедуру на C#, которая бы производила все нужные вычисления. Но и здесь я застрял — я не знаю, как получить текущее измерение (по аналогии с AXIS( 1 ).ITEM( 0 ).DIMENSION).