[SSAS] Une fonction Split en full MDX

J’en avais déjà parlé dans ce post, il manque une fonction Split à MDX. Non pas que cela ne puisse pas se coder dans l’absolu – les procédures stockées managées en .NET sont pour ça – mais je me suis dit qu’en coder un en MDX pouvait être une application marrante de la récursivité (bien que complètement inutile hormis mon plaisir personnel je vous l’avoue).
Alors en MDX comment faire? Il n’y a pas de boucles, donc la seule technique valable est d’utiliser la récursivité. Car oui MDX permet de faire des récursions, ce qui signifie qu’il autorise un membre à se faire référence à lui même dans sa définition. On a parfaitement le droit d’écrire ça par exemple:
WITH
MEMBER Measures.[Toto]
AS ([Date].[Date].PrevMember, Toto)*1.1
Pour plus de détails allez voir l’excellent post de Mosha à ce sujet.
Alors comment cela peut-il m’aider dans mon cas?
Commençons déjà par définir deux membres de base, ma chaîne et le caractère de Split:
WITH
MEMBER String
AS "0,1,22,333,4444,55555"

MEMBER Separator
AS ","
Le but va donc être de sortir une mesure qui pour un jeu de membres donnés va retourner toutes les sous-chaînes délimitées par le séparateur. Tout ce dont vous avez besoin c’est donc d’un ensemble de membres assez grand (plus de membres que d’occurences du séparateur) pour affecter votre mesure. J’ai pris le niveau fin de la dimension Date d’Adventure Works mais vous faites comme vous voulez.
Mon membre Splitter est défini comme suit:

MEMBER Splitter AS
CASE
WHEN ([Date].[Date].CurrentMember IS [Date].[Date].[Date].Members.Item(0))
AND (VBA!InStr(String,Separator) > 0)
THEN String
WHEN (VBA!InStr([Date].[Calendar].PrevMember,Separator) > 0)
THEN Right
(
[Date].[Calendar].PrevMember,
Len
(
[Date].[Calendar].PrevMember
)
-
InStr
(
[Date].[Calendar].PrevMember,
Separator
)
)
ELSE
NULL
END
Cas 1: Si on est au premier membre du jeu, on affecte le premier membre à la valeur de la chaîne de caractère initiale
Cas 2: Si on est un autre membre et qu’il reste des séparateurs dans la chaîne, on prend la partie droite du membre précédent (la récursivité est là) jusqu’au premier séparateur.
Cas 3: Le travail est terminé, on retourne NULL
Ce membre retourne cela:
C’est presque ce qu’il me faut. Je rajoute juste un membre qui prend la partie gauche de chaque valeur de Splitter:

MEMBER Splitted
AS
CASE
WHEN VBA!InStr(Splitter,Separator)>0
THEN VBA!Left(Splitter,VBA!InStr(Splitter,Separator)-1)
ELSE Splitter
END

SELECT [Splitted] ON 0,
NON EMPTY {[Date].[Date].[Date].Members} ON 1
FROM [Adventure Works]
Et j’obtiens:

Tadaaa. Certes assez inutile j’en conviens, mais à mon avis un bon exemple de l’utilisation de la récursivité pour de l’itération en MDX.
A bientôt!
EDIT du 28/04/2011: à signaler au passage ce superbe – comme souvent – article de Jeffrey Wang sur la récursivité en MDX: http://mdxdax.blogspot.com/2011/04/performance-considerations-for.html

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s