Définir dynamiquement une plage dans une dimension


18

J'ai un problème auquel je dois faire face chaque fois que je décide de construire un cube, et je n'ai pas encore trouvé de moyen de le surmonter.

Le problème est de savoir comment permettre à l'utilisateur de définir automatiquement une gamme de choses sans avoir à les coder en dur dans la dimension. Je vais expliquer mon problème dans un exemple.

J'ai une table appelée Clients :

Structure de la table

ce sont les données du tableau:

Tableau avec données

Je souhaite afficher les données dans un style pivot et regrouper le salaire et l' âge dans des plages définies comme ci-dessous:

Table avec des données avec une plage définie

J'ai écrit ce script et défini les plages:

SELECT [CustId]
      ,[CustName]
      ,[Age]
      ,[Salary]
      ,[SalaryRange] = case
        when cast(salary as float) <= 500 then
            '0 - 500'
        when cast(salary as float) between 501 and 1000 then
            '501 - 1000'
        when cast(salary as float) between 1001 and 2000 then
            '1001 - 2000'
        when cast(salary as float) > 2000 then
            '2001+'
        end,
        [AgeRange] = case
        when cast(age as float) < 15 then
            'below 15'
        when cast(age as float) between 15 and 19 then
            '15 - 19'
        when cast(age as float) between 20 and 29 then
            '20 - 29'               
        when cast(age as float) between 30 and 39 then
            '30 - 39'
        when cast(age as float) >= 40 then
            '40+'
        end
  FROM [Customers]
GO

Mes plages sont codées en dur et définies. Lorsque je copie les données dans Excel et les affiche dans un tableau croisé dynamique, elles apparaissent comme ci-dessous:

Données dans le tableau croisé dynamique

Mon problème est que je veux créer un cube en convertissant la table Customers en une table de faits et créer des tables à 2 dimensions SalaryDim & AgeDim .

La table SalaryDim comporte 2 colonnes ( SalaryKey, SalaryRange ) et la table AgeDim est similaire ( ageKey, AgeRange ). Ma table de faits client a:

Customer
[CustId]
[CustName]
[AgeKey] --> foreign Key to AgeDim
[Salarykey] --> foreign Key to SalaryDim

Je dois encore définir mes gammes à l'intérieur de ces dimensions. Chaque fois que je connecte un pivot Excel à mon cube, je ne peux voir que ces plages définies codées en dur.

Ma question est de savoir comment définir des plages de manière dynamique à partir du tableau croisé dynamique directement, sans créer les dimensions de la plage comme AgeDim et SalaryDim . Je ne veux pas seulement être collé aux plages définies dans la dimension.

Aucune plage définie

La plage définie est «0-25», «26-30», «31 - 50». Je pourrais vouloir le changer en "0-20", "21 -31", "32 -42" et ainsi de suite, et les utilisateurs demandent des plages différentes à chaque fois.

Chaque fois que je le change, je dois changer la dimension. Comment puis-je améliorer ce processus?

Ce serait formidable d'avoir une solution implémentée dans le cube, afin que n'importe quel outil client BI qui se connecte au cube puisse définir les plages, mais cela ne me dérangerait pas s'il existe un bon moyen d'utiliser uniquement Excel.

Réponses:


12

COMMENT FAIRE AVEC T-SQL:

Comme demandé, c'est une alternative à ma réponse précédente qui montrait comment le faire par utilisateur avec Excel. Cette réponse montre comment faire la même chose partagée / centralisée à l'aide de T-SQL à la place. Je ne sais pas comment faire Cubes, MDX ou SSAS pour ça, alors peut-être Benoit ou quelqu'un qui sait qui peut poster son équivalent ...

1. Ajouter une table et une vue SQL SalaryRanges

Créez une nouvelle table appelée "SalaryRangeData" avec la commande suivante:

Create Table SalaryRangeData(MinVal INT Primary Key)

Ajoutez des colonnes calculées en les enveloppant dans une vue avec cette commande:

CREATE VIEW SalaryRanges As
WITH
  cteSequence As
(
    Select  MinVal,
            ROW_NUMBER() OVER(Order By MinVal ASC) As Sequence
    From    SalaryRangeData
)
SELECT 
    D.Sequence,
    D.MinVal,
    COALESCE(N.MinVal - 1, 2147483645)  As MaxVal,
    CAST(D.MinVal As Varchar(32))
    + COALESCE(' - ' + CAST(N.MinVal - 1 As Varchar(32)), '+')
                        As RangeVals
FROM        cteSequence As D 
LEFT JOIN   cteSequence As N ON N.Sequence = D.Sequence + 1

Faites un clic droit sur le tableau dans SSMS et sélectionnez "Modifier les 200 premières lignes". Entrez ensuite les valeurs suivantes dans les cellules MinVal: 0, 501, 1001 et 2001 (l'ordre n'a pas d'importance pour SQL Server, il le créera pour nous). Fermez l'éditeur de lignes de table et effectuez une SELECT * FROM SalaryRangespour afficher toutes les lignes et les informations de plage.

2. Ajouter une table et une vue SQL AgeRanges

Suivez exactement les mêmes étapes qu'au point 1 ci-dessus, sauf remplacez toutes les occurrences de «Salaire» par «Âge». Cela devrait rendre la table "AgeRangeData" et la vue "AgeRanges".

Entrez les valeurs suivantes dans la colonne AgeRangeData [MinVal]: 0, 15, 20, 30 et 40.

3. Ajoutez des plages aux données

Remplacez votre instruction SELECT par des expressions CASE pour récupérer les données et les plages par la suivante:

SELECT [CustId]
      ,[CustName]
      ,[Age]
      ,[Salary]
      ,[SalaryRange] = (
            Select RangeVals From SalaryRanges
            Where [Salary] Between MinVal And MaxVal)
      ,[AgeRange] = (
            Select RangeVals From AgeRanges
            Where [Age] Between MinVal And MaxVal)
  FROM [Customers]

4. Tout le reste, comme maintenant

À partir d'ici, faites tout comme vous le faites actuellement. Les plages doivent toutes apparaître dans votre tableau croisé dynamique comme elles le font actuellement.

5. Testez la magie

Accédez à nouveau à l'éditeur de lignes de table SalaryRangeData dans SSMS et supprimez les lignes existantes, puis insérez les valeurs suivantes: 0, 101, 201, 301, ... 2001 (encore une fois, l'ordre n'a pas d'importance pour la solution T-SQL) . Revenez à votre tableau croisé dynamique et actualisez les données. Et tout comme la solution Excel, les plages de tableau croisé dynamique doivent être automatiquement modifiées.


Une addition

COMMENT L'AJOUTER À UN CUBE:

1. Créez une vue

CREATE VIEW CustomerView As
SELECT [CustId]
      ,[CustName]
      ,[Age]
      ,[Salary]
      ,[SalaryRange] = (
            Select RangeVals From SalaryRanges
            Where [Salary] Between MinVal And MaxVal)
      ,[AgeRange] = (
            Select RangeVals From AgeRanges
            Where [Age] Between MinVal And MaxVal)
  FROM [Customers]

1. Créez un projet BI dans Visual studio et ajoutez le CustomerView

Connectez-vous à la base de données et ajoutez la CustomerViewvue dans la Data Source Viewstable des faits

Vues des sources de données

2. Créez un cube et définissez la mesure et la dimension

nous avons seulement besoin de customerId, comme mesure du nombre de clients, et nous aurons la même table de faits qu'une dimension

Les mesures

Dimensions

3. Ajouter des attributs à la dimension

Ajouter des plages en tant qu'attributs à la dimension

4. Connectez-vous à Cube depuis Excel

Ajouter une source SSAS à Excel

Sélectionnez le cube

5. Affichez les données du cube dans Excel

Afficher le cube dans Excel

6. pour toute modification dans les plages, il suffit de retraiter la dimension et le cube

si vous devez modifier les plages, modifiez les données dans le SalaryRangeDatapuis AgeRangeDataet retraitez simplement les dimensions et le cube


8

COMMENT FAIRE AVEC EXCEL

Voici comment je le ferais dans Excel ...

1. Ajouter le tableau Excel SalaryRanges

Insérez une nouvelle feuille de calcul, appelez-la "échelles de salaire". Dans la première ligne, ajoutez les en-têtes de texte "Min", "Max" et "Range" dans cet ordre (doivent être les cellules A1, A2, A3, respectivement).

Dans la cellule B2, ajoutez la formule suivante:

=IF(A2="","",IF(A3="","+",A3-1))

Dans la cellule C2, ajoutez cette formule:

=IF(B2="","",A2 & IF(B2="+",""," - ") & B2)

Remplissez automatiquement ces deux formules dans les colonnes B et C pour le nombre maximal de lignes dont vous aurez besoin (disons 30).

Ensuite, sélectionnez toute la plage (A1..C31). Arrivé à l'onglet Insertion et cliquez sur le bouton Tableau pour changer cette plage en un tableau Excel (ceux-ci s'appelaient auparavant "Listes"). Dans l'onglet Conception des outils de table, changez le nom de cette table en "SalaryRanges".

Maintenant, allez à la cellule A2 dans la colonne Min et entrez "0", "501" dans A3, "1001" dans la cellule A4 et enfin "2001" dans la cellule A5. Notez que ce faisant, les colonnes MAx et Range sont automatiquement remplies.

2. Ajouter un tableau Excel AgeRanges

Maintenant, créez une autre nouvelle feuille de calcul nommée "Age Ranges", et effectuez exactement les mêmes étapes que dans # 1 ci-dessus, sauf appelez ce tableau "AgeRanges" et dans la colonne Min remplissez les cellules A2 à A6 avec 0, 15, 20, 30 et 40, dans l'ordre. Encore une fois, les valeurs Max et Range devraient se remplir automatiquement au fur et à mesure.

3. Obtenez les données

Récupérez les données de la base de données dans votre classeur Excel comme vous l'avez fait auparavant (ne créez pas encore le tableau croisé dynamique, nous le faisons ci-dessous), sauf que vous devez supprimer les colonnes de fonction de cas AgeRange et SalaryRange.

4. Ajoutez les colonnes Salaire et Tranche d'âge à vos données

Dans la feuille où se trouvent vos données, ajoutez une colonne "SalaryRange" et "AgeRange". Dans la colonne SalaryRange, remplissez automatiquement la formule suivante (en supposant que "D" est la colonne Salary):

=LOOKUP(D2,SalaryRanges)

Et remplissez automatiquement cette formule dans la colonne AgeRange (en supposant que "C" est la colonne Age):

=LOOKUP(C2,AgeRanges)

5. Créez votre tableau croisé dynamique

Faites-le comme vous l'avez fait auparavant. Notez que la valeur / les étiquettes de plage d'âge et de salaire correspondent aux plages que vous choisissez.

6. Testez la magie

Maintenant, la partie amusante. Accédez à la feuille de calcul SalaryRanges et entrez à nouveau dans la colonne Min, en commençant à 0, puis 101, 201, 301, ... 2001. Revenez à votre tableau croisé dynamique et actualisez-le. Shazaam!


Je dois mentionner que bien sûr, vous pouvez également obtenir le même effet en mettant les tables en SQL et en modifiant votre instruction SELECT pour faire les LOOKUP (..) s en tant que sous-requête (un peu compliqué à cause de la correspondance de plage, mais certainement- capable). La raison pour laquelle je l'ai fait de cette façon (dans Excel) est

  1. Changer la gamme est un peu plus facile pour la plupart des gens. Même pour les DBA et les développeurs SQL (comme nous), cette façon est un peu plus facile simplement parce qu'elle est plus proche de l'interface utilisateur / des résultats.
  2. Cela permet à vos utilisateurs de modifier leurs propres plages sans avoir à vous déranger. (un GRAND plus dans ma vie)
  3. Cela permet également à chaque utilisateur de définir ses propres plages.

Cependant, il n'est parfois pas souhaitable que les utilisateurs définissent leurs propres plages. Si c'est le cas pour vous, je serai heureux de vous montrer comment le faire de manière centralisée, en SQL à la place.


+1 et Merci beaucoup, la solution fonctionne à merveille, en connectant la table avec les données avec les plages tout en excel, Existe-t-il un moyen de connecter ces plages définies avec le tableau croisé dynamique qui est connecté au Cube, mes pivots sont directement connectés au cube dans SSAS, et aussi ce serait génial si vous pouvez montrer "comment le faire de manière centralisée".
AmmarR

Je peux vous montrer comment le faire de manière centralisée avec des expressions SQL, je posterai cela comme une réponse alternative. Je ne peux pas résoudre les problèmes Cube / SSAS car malheureusement je ne les connais pas. Oui, je devrais les connaître et j'aimerais bien le faire, mais je ne le sais pas, donc quelqu'un d'autre devra y répondre.
RBarryYoung

5

Avec le langage MDX, vous pouvez créer des membres personnalisés qui définiront les plages. L'expression suivante a défini un membre calculé qui représente tous les salaires entre 501 et 1000:

MEMBER [Salary].[between_500_and_1000] AS Aggregate(Filter([Salary].Members, [Salary].CurrentMember.MemberValue > 500 AND [Salary].CurrentMember.MemberValue <= 1000))

Vous pouvez faire la même chose avec la dimension âge:

MEMBER [Age].[between_0_and_25] AS Aggregate(Filter([Age].Members, [Age].CurrentMember.MemberValue <= 25))

Cet article explique comment ajouter ces membres calculés dans Excel (voir la section « Création de membres / mesures calculés et d'ensembles dans Excel 2007 OLAP PivotTables »). Malheureusement, il n'y a pas d'interface utilisateur dans Excel pour cela. Néanmoins, vous pouvez trouver des clients BI qui prennent en charge le langage MDX , qui permettent de définir vos plages dans les requêtes.


merci @Benoit, j'essaie d'ajouter des champs calculés dans le cube lui-même avec le même concept que vous suggérez mais je ne semble pas encore fonctionner, le processus est un peu long et je ne le connais pas je vais l'essayer avec excel ainsi,
AmmarR

Merci @RBarryYoung. @ MarkStorey-Smith: Je peux améliorer l'efficacité de la formule, si vous me donnez la liste des niveaux qui se trouvent dans la dimension Salaryet Age.
Benoit
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.