SQL Developpement: La clause MODEL

SQL Developpement: La clause MODEL

La clause MODEL

Dans une feuille de calcul d’un tableur, on peut très simplement effectuer des calculs mettant en jeu les cellules de cette feuille de calcul. Ainsi vous pouvez ajouter la troisième colonne de la deuxième ligne à la cinquième colonne de la cinquième ligne ou ajouter une nouvelle ligne à partir de la somme des deux ou plusieurs autres existantes. Les tableurs vous permettent de traiter chaque ligne et colonne de données et l’utiliser dans une formule ce qui est très difficile voire impossible de faire en SQL classique.

A partir de la version Oracle 10g, une nouvelle fonctionnalité appelée la clause « MODEL » est introduite avec le niveau de performance d’un tableur classique.

563.png

La syntaxe de la clause « MODEL » est trop complexe pour être décrite dans son ensemble, et nous allons de ce fait commencer par la décrire partiellement comme suit :

SELECT * FROM   …

MODEL [ RETURN { UPDATED | ALL } ROWS ]

[ MAIN nom_du_modèle ]

     PARTITION BY ( expression[,…])

     DIMENSION BY ( expression[,…])

     MEASURES ( métrique[,…])

     RULES ( métrique [expression[,…]][,…] ) ;

RETURN                           La description des enregistrements qui sont retournés ; « ALL » tous les enregistrements, « UPDATED » uniquement les enregistrements calculés.

PARTITION BY             La définition des colonnes utilisées pour partitionner les lignes sélectionnées.

DIMENSION BY             La définition des colonnes donnant le niveau de l’enregistrement pour le calcul à l’intérieur de la partition. Les valeurs des ces colonnes permettent d’identifier une celule dans le tableau.

MEASURES                      La définition des colonnes métriques qui sont utilisées pour les calculs dans le modèle.

RULES                             La définition des cellules qui seront affectées par le calcul et le mode d’application des règles. Chaque règle représente une affectation dans laquelle l’opérande gauche désigne les cellules à mettre à jour et l’opérande droit représente les valeurs à affecter à ces cellules. Si la cellule n’existe pas alors elle est créée.

métrique[val]           La description d’une cellule du tableau. La valeur peut être une constante qui represente une valeur de la dimension déjà existante dans le tableau ou une nouvelle valeur pour le nouvel enregistrement.

560.png

SQL> WITH QM_2010 AS (

  2      SELECT MOIS, SUM(QUANTITE) Q

  3      FROM COMMANDES NATURAL JOIN DETAILS_COMMANDES

  4      WHERE ANNEE = 2010 GROUP BY MOIS)

  5  SELECT MOIS, Q FROM QM_2010

  6      MODEL DIMENSION BY (MOIS) MEASURES (Q)

  7      RULES ( Q[8.5] = Q[7]+Q[8], Q[12.5] = Q[11]+Q[12]) ORDER BY MOIS;

      MOIS           Q

———- ———–

         1   2 586 939

         2   2 422 312

         3   2 562 429

         4   2 413 987

         5   2 662 399

         6   2 538 585

         7   2 568 649

         8   2 722 756

       8,5   5 291 405    <= 2 568 649 + 2 722 756

         9   2 491 305

        10   2 823 864

        11   2 579 959

        12   2 458 342

      12,5   5 038 301    <= 2 579 959 + 2 458 342

Dans l’exemple précédent, la requête retourne les quantités mensuelles vendues pour l’année 2010. Il y a deux enregistrements supplémentaires : le premier est la somme des quantités vendues pour les mois de juillet et août et le deuxième représente la somme des quantités vendues pour les mois de novembre et décembre. Les deux enregistrements sont initialisés à l’aide de la syntaxe :

nom_métrique [ nouvelle valeur dimension ] = expression

Il faut être attentif car il n’est pas possible d’utiliser une constante de type différent du type de la dimension correspondante, sauf dans le cas des conversions implicites. Dans l’exemple précédent, pour les deux enregistrements, les valeurs attribuées pour la dimension M sont respectivement 8,5 et 12,5.

Il est possible de n’afficher que les enregistrements calculés à l’aide de la syntaxe « RETURN UPDATES ROWS » ; l’exécution de l’exemple précédent est alors comme dans l’exemple suivant.

SQL> WITH QM_2010 AS (

  7      MODEL RETURN UPDATED ROWS

      MOIS           Q

———- ———–

       8,5   5 291 405

      12,5   5 038 301

Vous avez la possibilité d’utiliser et afficher toutes les colonnes qui sont déclarées dans la syntaxe de la clause « MODEL ». Qu’il s’agisse de « PARTITION BY », « DIMENSION BY » ou « MEASURES », toutes ces colonnes sont accessibles en calcul ou affichage.

Mais attention, aucune autre colonne n’est accessible pour l’affichage ou le calcul ; ainsi, si vous avez besoin d’afficher ou de traiter une colonne, il faut prévoir de l’inclure dans les déclarations de la clause « MODEL ».

SQL> SELECT ANNEE, MOIS, P FROM (

  2      SELECT ANNEE, MOIS, SUM(PORT) P FROM COMMANDES

  3      WHERE ANNEE = 2011 GROUP BY ANNEE, MOIS) SR

  4  MODEL DIMENSION BY (MOIS) MEASURES (P) RULES();

  SELECT ANNEE, MOIS, P FROM (

         *

ERREUR à la ligne 1 :

ORA-32614: expression MODEL SELECT interdite

SQL> SELECT MOIS, P FROM (SELECT ANNEE, MOIS, SUM(PORT) P FROM COMMANDES

  2      WHERE ANNEE = 2011 GROUP BY ANNEE, MOIS) SR

  3  MODEL DIMENSION BY (MOIS) MEASURES (P) RULES();

      MOIS          P

———- ———-

         2    66132,7

         6    69621,7

         1    65722,3

         5    67417,3

         3    73703,4

         4    68543,4

Dans l’exemple précédent uniquement, la requête qui affiche les colonnes présentes dans la syntaxe de la clause « MODEL » peut être exécutée bien que la clause n’effectue aucune opération.

Dans la description des dimensions, vous pouvez utiliser une ou plusieurs colonnes pour déterminer le niveau d’agrégation, mais par la suite la liste entière des ces colonnes doit être utilisée pour identifier les cellules du tableau.

Dans l’exemple précédent, vous pouvez voir que la somme pour les catégories ‘Viandes’, ‘Viande en conserve’ et ‘Poissons et fruits de mer’ est effectuée uniquement pour les ventes qui on été faites en ‘France’.

SQL> WITH

  2  PCQ_2010_01 AS (

  3  SELECT PAYS, NOM_CATEGORIE CATEGORIE, SUM(DC.QUANTITE) Q

  4  FROM CLIENTS CL NATURAL JOIN COMMANDES CO

  5          NATURAL JOIN DETAILS_COMMANDES DC

  6                  JOIN PRODUITS   USING(REF_PRODUIT)

  7                  JOIN CATEGORIES USING(CODE_CATEGORIE)

  8  WHERE PAYS IN (‘Allemagne’,’France’)

  9    AND ANNEE = 2011 AND MOIS = 1 AND CODE_CATEGORIE > 5

 10  GROUP BY PAYS, NOM_CATEGORIE)

 11  SELECT PAYS, CATEGORIE, Q FROM PCQ_2010_01

 12      MODEL DIMENSION BY (PAYS,CATEGORIE) MEASURES (Q)

 13      RULES ( Q[‘France’,’Viandes et Poissons’] =

 14        Q[‘France’,’Viandes’]+ Q[‘France’,’Viande en conserve’] +

 15        Q[‘France’,’Poissons et fruits de mer’])ORDER BY PAYS,CATEGORIE;

PAYS      CATEGORIE                       Q

——— ————————- ——-

Allemagne Conserves                  31 976

Allemagne Poissons et fruits de mer  41 059

Allemagne Produits secs              42 383

Allemagne Viande en conserve         10 323

Allemagne Viandes                    21 255

France    Conserves                  32 195

France    Poissons et fruits de mer  40 964

France    Produits secs              39 467

France    Viande en conserve         11 324

France    Viandes                    22 512

France    Viandes et Poissons        74 800 <= 40964 + 11324 + 22512

A l’aide de la clause « MODEL » vous pouvez calculer des nouveaux enregistrements mais également modifier les valeurs des enregistrements existants. Il faut cependant être attentif car les calculs ultérieurs définis dans la clause « MODEL » sont effectués avec ces valeurs.

SQL> WITH PPA_AUT AS (

  2  SELECT PAYS, ANNEE, SUM(PORT) P

  3                  FROM COMMANDES NATURAL JOIN CLIENTS

  4                  WHERE PAYS = ‘Autriche’

  5                  GROUP BY PAYS, ANNEE)

  6  SELECT * FROM PPA_AUT

  7  UNION ALL

  8  SELECT * FROM PPA_AUT

  9  MODEL DIMENSION BY (PAYS,ANNEE) MEASURES (P)

 10      RULES ( P[‘Autriche’,2008] = P[‘Autriche’,2010],

 11              P[‘Autriche’,2009] =

 12              P[‘Autriche’,2010]+P[‘Autriche’,2011],

 13              P[‘Autriche’,2010] = 0,

 14              P[‘Autriche’,2012] =

 15              P[‘Autriche’,2010]+P[‘Autriche’,2011]);

PAYS        ANNEE         P

———– —– ———

Autriche     2010  12 679,5

Autriche     2011   7 011,7       <= enregistrements initiaux

Autriche     2010        ,0

Autriche     2011   7 011,7

Autriche     2009  19 691,2

Autriche     2008  12 679,5

Autriche     2012   7 011,7

Dans l’exemple précédent, les deux premiers enregistrements sont les enregistrements initiaux. Il y a quatre calculs dans la clause « MODEL » pour les années 2008, 2009, 2010 et 2012. Le premier calcul affiché pour l’année 2008 est la valeur de frais de port de l’année 2010 initiale avant sa modification. Le deuxième calcul affiché pour l’année 2009 est la somme des frais de port des années 2010 et 2011 avant la modification de la valeur de l’année 2010. Le troisième calcul modifie la valeur des frais de port pour l’année 2010 en la mettant à 0. Le quatrième calcul affiché pour l’année 2012 est identique au deuxième mais il est exécuté après la modification des frais de port pour de l’année 2010, et alors la valeur trouvée est uniquement donnée par les frais de port de l’année 2011.

Vous pouvez utiliser plusieurs métriques à partir de la sous-requête principale, mais vous avez également la possibilité d’introduire des nouvelles directement dans la syntaxe de la clause « MODEL » comme suit :

MEASURES ( { métrique | expression } [AS alias] [,…] )

SQL> WITH QPPA_FS AS (

  2      SELECT PAYS, ANNEE, SUM(PORT) P, SUM(QUANTITE) Q

  3      FROM CLIENTS NATURAL JOIN COMMANDES

  4                   NATURAL JOIN DETAILS_COMMANDES

  5      WHERE PAYS = ‘France’ AND REF_PRODUIT = 1

  6      GROUP BY PAYS, ANNEE)

  7  SELECT * FROM QPPA_FS

  8  MODEL DIMENSION BY (PAYS, ANNEE) MEASURES (P,Q,0 C)

  9  RULES ( C[‘France’,2010] = P[‘France’,2010]/Q[‘France’,2010],

 10          C[‘France’,2011] = P[‘France’,2011]/Q[‘France’,2011],

 11          P[‘France’,2012] = P[‘France’,2010]+P[‘France’,2011],

 12          Q[‘France’,2012] = Q[‘France’,2010]+Q[‘France’,2011],

 13          C[‘France’,2012] = P[‘France’,2012]/Q[‘France’,2012])

 14  ORDER BY 2;

PAYS    ANNEE         P         Q       C

——- —– ——— ——— ——-

France   2010  19 878,9  29 972,0  0,6632

France   2011  14 779,2  21 466,0  0,6885

France   2012  34 658,1  51 438,0  0,6738

Dans l’exemple précédent, les deux métriques P et Q sont des champs de la sous-requête principale ; par contre C est une colonne décrite dans la clause « MODEL ». Il est impératif dans ce cas de fournir une constante ou une expression pour déterminer le type de la colonne. Attention, toutes les opérations futures avec cette colonne doivent respecter ce type comme pour toute colonne d’une table.

La condition « IS PRESENT » est une autre condition typique de la clause « MODEL » permettant de tester l’existence d’une cellule dans le tableau.

SQL> WITH VMPQ AS (

  2      SELECT PAYS, DATE_COMMANDE D, SUM(PORT) P

  3      FROM CLIENTS JOIN COMMANDES USING (CODE_CLIENT)

  4           JOIN DETAILS_COMMANDES USING (NO_COMMANDE)

  5      WHERE DATE_COMMANDE > ’20/06/2011′ AND PAYS IN (‘France’)

  6        AND REF_PRODUIT = 110 GROUP BY PAYS, DATE_COMMANDE )

  7  SELECT * FROM VMPQ

  8  MODEL DIMENSION BY (PAYS,D) MEASURES (P,TO_NUMBER(NULL) T)

  9  RULES ( T[‘France’,’22/06/2011′]=

 10          CASE WHEN P[‘France’,’22/06/2011′] IS PRESENT

 11          THEN P[‘France’,’22/06/2011′]  ELSE NULL END,

 12          T[‘France’,’25/06/2011′]=

 13          CASE WHEN P[‘France’,’25/06/2011′] IS PRESENT

 14          THEN P[‘France’,’25/06/2011′]  ELSE NULL END

 15         )ORDER BY 1,2,3;

PAYS        D               P      T

———– ———- —— ——

France      21/06/2011  243,0 ——

France      22/06/2011   67,1   67,1

France      25/06/2011 —— —— <= nouvel enregistrement

France      28/06/2011   87,5 ——

France      29/06/2011   66,4 ——

France      30/06/2011   93,0 ——

La modification des cellules

La syntaxe pour décrire les colonnes de type métrique dans les règles est la suivante :

… RULES [{ UPDATE | UPSERT [ALL] }] …

UPDATE                           L’option force la base de données à appliquer les règles sur l’ensemble des cellules référencées dans l’opérande gauche qui existent dans le tableau multidimensionnel. Si la cellule n’existe pas, la règle est ignorée.

UPSERT                           L’option force la base de données à appliquer les règles sur l’ensemble des cellules référencées dans l’opérande gauche qui existent dans le tableau multidimensionnel et à créer des nouvelles lignes pour les cellules qui n’existent pas. Attention, si l’argument « ALL » n’est pas défini, la règle ne s’applique qu’avec un opérande gauche uni-colonne référencé par position, c’est l’option par défaut.

Dans l’exemple suivant vous pouvez remarquer que dans le cas d’utilisation de l’option « UPDATE » et de l’enregistrement qui n’existe pas alors, il n’y a aucune modification car l’affichage ne concerne que les enregistrements modifiés suite à l’option « RETURN UPDATED ROWS ».

SQL> SELECT * FROM (

  2     SELECT DT.MOIS, SUM(PORT) P FROM COMMANDES JOIN DIM_TEMPS DT

  3     ON( DATE_COMMANDE = JOUR) WHERE DT.ANNEE = 2011 GROUP BY DT.MOIS )

  4  MODEL RETURN UPDATED ROWS DIMENSION BY (MOIS) MEASURES (P)

  5  RULES UPDATE( P[‘Total’] = SUM(P)[MOIS LIKE ‘%’] );

aucune ligne sélectionnée

SQL> SELECT * FROM (

  2     SELECT DT.MOIS, SUM(PORT) P FROM COMMANDES JOIN DIM_TEMPS DT

  3     ON( DATE_COMMANDE = JOUR) WHERE DT.ANNEE = 2011 GROUP BY DT.MOIS )

  4  MODEL RETURN UPDATED ROWS DIMENSION BY (MOIS) MEASURES (P)

  5  RULES UPSERT ( P[‘Total’] = SUM(P)[MOIS LIKE ‘%’] );

MOIS                        P

—————— ———-

Total                411140,8

Les deux requêtes de l’exemple précédent utilisent dans les règles une fonction agrégat car il s’agit dans ce cas d’un calcul sur l’ensemble des enregistrements de la source de données. Le calcul est effectué uniquement sur les enregistrements qui vérifient la condition décrite entre les crochets, dans notre exemple, il s’agit des tous les enregistrements.

Vous pouvez utiliser la condition « ANY », valable pour effectuer des calculs pour tous les enregistrements d’une dimension de la clause « MODEL », à l’aide de la syntaxe suivante :

 [nom dimension IS] ANY

En cas d’utilisation d’une condition à la place d’une constante il s’agit d’un calcul multi-cellules.

Attention, toute utilisation d’accès multi-cellule se solde avec une erreur si vous n’utilisez pas des fonctions d’agrégat.

559.png

Vous pouvez utiliser une fonction d’agrégat pour les valeurs d’un ensemble de cellules en utilisant la syntaxe suivante :

fonction_aggrégat( métrique )[ dimension[,…] ]

Dans l’exemple suivant, vous pouvez voir trois enregistrements calculés. Le premier calcul affiché pour la France est la somme de quantités vendues en France pour les mois de janvier et de février. Le deuxième affiché pour la Suisse est la somme des quantités vendues en Suisse pour les mois d’avril et mai. Le dernier calcul est affiché pour Italie, mais il somme les ventes dans tous les pays pour le mois de juin.

SQL> WITH VMPQ AS (SELECT DT.MOIS_N M, DT.MOIS, PAYS, SUM(DC.QUANTITE) Q

  2      FROM CLIENTS JOIN COMMANDES CO USING (CODE_CLIENT)   

  3           JOIN DETAILS_COMMANDES DC USING (NO_COMMANDE)

  4           JOIN PRODUITS             USING (REF_PRODUIT)

  5           JOIN DIM_TEMPS DT            ON( DATE_COMMANDE = JOUR)

  6      WHERE CO.ANNEE = 2011 AND REF_PRODUIT < 5

  7        AND NO_EMPLOYE IN (45,47,73) GROUP BY DT.MOIS_N, DT.MOIS, PAYS )

  8  SELECT * FROM VMPQ   

  9  MODEL DIMENSION BY (M,MOIS,PAYS) MEASURES (Q)

 10  RULES UPSERT ALL

 11  ( Q[7,’Total Jan Mar’,’France’] = SUM(Q)[M < 3,ANY,’France’] ,

 12    Q[7,’Total Avr Mai’,’Suisse’] = SUM(Q)[M IN (4,5),ANY,’Suisse’],

 13    Q[7,’Total Juin’   ,’Italie’] = SUM(Q)[M = 6,ANY,ANY])

 14  ORDER BY  1,3;

 

  M MOIS               PAYS                Q

— —————— ————– ——

  1 Janvier            France           4616

  1 Janvier            Italie            720

  1 Janvier            Suisse            271

  2 Février            France           3521

  2 Février            Italie            644

  2 Février            Suisse            288

  3 Mars               France           4725

  3 Mars               Italie           2874

  3 Mars               Suisse            354

  4 Avril              France           3391

  4 Avril              Italie            987

  5 Mai                France           4946

  5 Mai                Italie            789

  5 Mai                Suisse            690

  6 Juin               France           4746

  6 Juin               Italie            553

  6 Juin               Suisse            293

  7 Total Jan Mar      France           8137 <= 4616 + 3521

  7 Total Juin         Italie           5592 <= 4746 + 553 + 293

  7 Total Avr Mai      Suisse            690 <= 690

Vous pouvez utiliser la condition « ANY » pour effectuer le calcul pour toutes les valeurs de la dimension correspondante. Il ne faut pas oublier d’ajouter l’option « UPSERT ALL », sans quoi les enregistrements ne sont pas affichés.

SQL> SELECT * FROM

  2   ( SELECT DT.ANNEE, DT.MOIS, SUM(PORT) P FROM COMMANDES JOIN

  3     DIM_TEMPS DT ON( DATE_COMMANDE = JOUR ) GROUP BY DT.ANNEE, DT.MOIS)

  4  MODEL RETURN UPDATED ROWS     

  5  DIMENSION BY (ANNEE,MOIS) MEASURES (P)   

  6  RULES UPSERT ( P[ANY ,’Total’] = SUM(P)[ANY,ANY] );

aucune ligne sélectionnée

SQL> SELECT * FROM

  2   ( SELECT DT.ANNEE, DT.MOIS, SUM(PORT) P FROM COMMANDES JOIN

  3     DIM_TEMPS DT ON( DATE_COMMANDE = JOUR ) GROUP BY DT.ANNEE, DT.MOIS)

  4  MODEL RETURN UPDATED ROWS MAIN model_mp   

  5  DIMENSION BY (ANNEE,MOIS) MEASURES (P)   

  6  RULES UPSERT ALL ( P[ANY ,’Total’] = SUM(P)[ANY,ANY] );

     ANNEE MOIS                P

———- ——– ————

      2010 Total       1 007 454

      2011 Total       2 014 907

La fonction CV

La fonction « CURRENTV » ou son alias « CV » permettent de récupérer la valeur courante d’une dimension définie dans la règle et permet un indexage relatif. Les données renvoyées sont du type de la colonne de la dimension. Sans argument, la fonction utilise la dimension associée avec la position relative d’écriture dans la fonction.

SQL> WITH VMPQ AS (SELECT DT.MOIS_N M, DT.MOIS, PAYS, SUM(DC.QUANTITE) Q

  2      FROM CLIENTS JOIN COMMANDES CO USING (CODE_CLIENT)   

  3           JOIN DETAILS_COMMANDES DC USING (NO_COMMANDE)

  4           JOIN DIM_TEMPS DT ON( DATE_COMMANDE = JOUR)

  5      WHERE CO.ANNEE = 2011 AND NO_EMPLOYE IN (45,47)

  6      GROUP BY DT.MOIS_N, DT.MOIS, PAYS )

  7  SELECT PAYS,MOIS,Q1,Q2,Q3 FROM VMPQ

  8  MODEL DIMENSION BY (M,MOIS,PAYS) MEASURES (Q Q1,0 Q2,0 Q3)

  9  RULES UPSERT ALL( Q1[7,’Total’,ANY] =  SUM(Q1)[ANY,ANY,CV()],

 10         Q2[ANY,ANY,ANY] = Q1[CV(),CV(),CV()],

 11         Q3[ANY,ANY,ANY] = SUM(Q2)[CV(),CV(),ANY]) ORDER BY  PAYS,M;

PAYS   MOIS           Q1       Q2       Q3

—— ——– ——– ——– ——–

France Janvier   108 331  108 331  118 108   <= 108 331 + 9 777

France Février   105 103  105 103  112 950

France Mars      110 334  110 334  135 474

France Avril     105 589  105 589  107 884

France Mai       141 985  141 985  160 145

France Juin      120 750  120 750  138 806

France Total     692 092  692 092  773 367

Suisse Janvier     9 777    9 777  118 108

Suisse Février     7 847    7 847  112 950

Suisse Mars       25 140   25 140  135 474

Suisse Avril       2 295    2 295  107 884

Suisse Mai        18 160   18 160  160 145

Suisse Juin       18 056   18 056  138 806

Suisse Total      81 275   81 275  773 367

L’exemple précédent permet d’afficher la colonne Q2 avec la même information que pour la colonne Q1 et calculer dans la colonne Q3 la somme de quantités vendues pour le même mois tous pays confondus. Un enregistrement de plus est affiché pour chaque pays et représente la somme des toutes les quantités vendues pour le pays.

SQL> SELECT * FROM ( SELECT ANNEE, MOIS, SUM(PORT) P1 FROM COMMANDES

  2  WHERE NO_EMPLOYE = 12 AND MOIS BETWEEN 1 AND 3 GROUP BY ANNEE, MOIS)

  3  MODEL DIMENSION BY(ANNEE,MOIS) MEASURES(P1,0 P2,0 P3,0 P4,0 P5)          

  4  RULES UPSERT ALL( P1[ANY,4] = SUM(P1)[CURRENTV(ANNEE),ANY] ,

  5    P2[ANY,ANY     ] = P1[CURRENTV(),CV(MOIS)],

  6    P3[ANY,MOIS < 4] = P1[CV()+1,CV()],

  7    P4[ANY,MOIS < 4] = SUM(P1)[ANY,CV()],

  8    P5[ANY,MOIS < 4] = SUM(P1)[CV(),MOIS < 4])

  9  ORDER BY ANNEE, MOIS;

ANNEE  MOIS        P       P1       P2       P3       P4

—– —– ——– ——– ——– ——– ——–

 2010     1    661,0    661,0    956,7  1 617,7  1 553,0

 2010     2    424,4    424,4    744,4  1 168,8  1 553,0

 2010     3    467,6    467,6    662,1  1 129,7  1 553,0

 2010     4  1 553,0  1 553,0 ——– ——– ——–

 2011     1    956,7    956,7 ——–  1 617,7  2 363,2

 2011     2    744,4    744,4 ——–  1 168,8  2 363,2

 2011     3    662,1    662,1 ——–  1 129,7  2 363,2

 2011     4  2 363,2  2 363,2 ——– ——– ——–

La requête suivante effectue cinq calculs qui sont affichés dans les colonnes de métriques. Le premier calcul est la somme des frais de port pour l’année en cours affichée dans le mois 4, pour chaque année de la requête principale. La deuxième règle copie les valeurs de la colonne P1 pour chaque enregistrement et les affiche dans la colonne P2. La troisième règle de calcul copie dans la colonne P3 les valeurs de l’année suivante pour le même mois si le numéro du mois est < 4. La quatrième règle de calcul affiche dans la colonne P4, si le numéro du mois est < 4, la somme des frais de port pour le même mois dans toutes les années. La dernière règle permet de calculer la somme des frais de port de l’année courante.

Dans l’exemple suivant, la colonne Q2 affiche pour le même pays la différence entre les quantités vendues dans le mois précédent, si l’enregistrement existe, et le mois courant. La colonne Q3 représente le poids des quantités vendues pour le pays courant par rapport à la somme des ventes pour le mois courant.

SQL> WITH VMPQ AS ( SELECT MOIS, PAYS, SUM(DC.QUANTITE) Q

  2   FROM CLIENTS JOIN COMMANDES CO USING (CODE_CLIENT)   

  3                JOIN DETAILS_COMMANDES DC USING (NO_COMMANDE)

  4   WHERE CO.ANNEE = 2011 AND NO_EMPLOYE IN (45,47) GROUP BY MOIS, PAYS )

  5  SELECT PAYS,MOIS,Q1,Q2,Q3 FROM VMPQ   

  6  MODEL DIMENSION BY (MOIS,PAYS) MEASURES (Q Q1,0 Q2,0 Q3)

  7  RULES ( Q2[ANY,ANY] = Q1[CV(),CV()] –

  8  CASE WHEN Q1[CV()-1,CV()] IS PRESENT

  9  THEN Q1[CV()-1,CV()] ELSE NULL END,

 10          Q3[ANY,ANY] = Q1[CV(),CV()] * 100 / SUM(Q1)[CV(),ANY])

 11  ORDER BY  PAYS,MOIS;

PAYS   MOIS       Q1       Q2       Q3

—— —- ——– ——– ——–

France    1  108 331 ——–    91,72

France    2  105 103   -3 228    93,05

France    3  110 334    5 231    81,44

France    4  105 589   -4 745    97,87

France    5  141 985   36 396    88,66

France    6  120 750  -21 235    86,99

Suisse    1    9 777 ——–     8,28

Suisse    2    7 847   -1 930     6,95

Suisse    3   25 140   17 293    18,56

Suisse    4    2 295  -22 845     2,13

Suisse    5   18 160   15 865    11,34

Suisse    6   18 056     -104    13,01

Les créations multiples

Si vous utilisez la condition « ANY » à gauche de l’égal de la règle pour effectuer le calcul de toutes les valeurs d’une dimension unique, il n’y a aucune contrainte. Dans le cas des dimensions multiples, l’utilisation de la condition  « ANY » pour toutes les dimensions, le fonctionnement est celui décrit précédemment. Maintenant si vous avez plusieurs dimensions et que l’utilisation de la condition « ANY » se limite à un nombre inférieur au total des dimensions, le nombre d’enregistrements modifiés ou insérés est égal au résultat de la requête « SELECT DISTINCT » de la liste des colonnes qui n’ont pas la condition « ANY ».

STAG01@topaze>SELECT PAYS, ANNEE, MOIS, SUM(PORT) P

  2  FROM COMMANDES JOIN CLIENTS USING(CODE_CLIENT)

  3  WHERE (PAYS=’France’ AND MOIS<3 )OR(PAYS=’Finlande’ AND MOIS<5 )

  4  GROUP BY PAYS, ANNEE, MOIS ORDER BY 1,2,3;

PAYS          ANNEE       MOIS               P

——– ———- ———- —————

Finlande       2010          1          844,30

Finlande       2010          2          926,50

Finlande       2010          3          981,90

Finlande       2010          4        1 006,70

Finlande       2011          1        1 118,30

Finlande       2011          2          759,20

Finlande       2011          3        1 763,30

Finlande       2011          4          804,70

France         2010          1        7 079,20

France         2010          2        5 232,20

France         2011          1        7 698,20

France         2011          2        8 747,90

STAG01@topaze>SELECT * FROM (SELECT PAYS, ANNEE, MOIS, SUM(PORT) P

  2      FROM COMMANDES JOIN CLIENTS USING(CODE_CLIENT)

  3      WHERE (PAYS = ‘France’ AND MOIS < 3 ) OR

  4            (PAYS = ‘Finlande’ AND MOIS < 5 )

  5     GROUP BY PAYS, ANNEE, MOIS )

  6  MODEL RETURN UPDATED ROWS

  7  DIMENSION BY (PAYS, ANNEE, MOIS) MEASURES (P)

  8  RULES UPSERT ALL (

  9        P[‘Nouveau Pays’,ANY,ANY] = sum(P)[ANY,CV(),CV()] )

 10  ORDER BY 1,2,3;

PAYS                  ANNEE       MOIS            P

—————- ———- ———- ————

Nouveau Pays           2010          1        7 924

Nouveau Pays           2010          2        6 159

Nouveau Pays           2010          3          982

Nouveau Pays           2010          4        1 007

Nouveau Pays           2011          1        8 817

Nouveau Pays           2011          2        9 507

Nouveau Pays           2011          3        1 763

Nouveau Pays           2011          4          805

STAG01@topaze>SELECT * FROM (SELECT PAYS, ANNEE, MOIS, SUM(PORT) P

  2      FROM COMMANDES JOIN CLIENTS USING(CODE_CLIENT)

  3      WHERE (PAYS = ‘France’ AND MOIS < 3 ) OR

  4            (PAYS = ‘Finlande’ AND MOIS < 5 )

  5     GROUP BY PAYS, ANNEE, MOIS )

  6  MODEL RETURN UPDATED ROWS

  7  DIMENSION BY (PAYS, ANNEE, MOIS) MEASURES (P)

  8  RULES UPSERT ALL (

  9        P[‘Nouveau Pays’,2011,ANY] = sum(P)[ANY,CV(),CV()] )

 10  ORDER BY 1,2,3;

PAYS                  ANNEE       MOIS            P

—————- ———- ———- ————

Nouveau Pays           2011          1        8 817

Nouveau Pays           2011          2        9 507

Nouveau Pays           2011          3        1 763

Nouveau Pays           2011          4          805

STAG01@topaze>SELECT * FROM (SELECT PAYS, ANNEE, MOIS, SUM(PORT) P

  2      FROM COMMANDES JOIN CLIENTS USING(CODE_CLIENT)

  3      WHERE (PAYS = ‘France’ AND MOIS < 3 ) OR

  4            (PAYS = ‘Finlande’ AND MOIS < 5 )

  5     GROUP BY PAYS, ANNEE, MOIS )

  6  MODEL RETURN UPDATED ROWS

  7  DIMENSION BY (PAYS, ANNEE, MOIS) MEASURES (P)

  8  RULES UPSERT ALL (

  9        P[‘France’,2010,ANY] = P[CV(),CV(),CV()] )

 10  ORDER BY 1,2,3;

PAYS          ANNEE       MOIS            P

——– ———- ———- ————

France         2010          1        7 079

France         2010          2        5 232

France         2010          3

France         2010          4

STAG01@topaze>SELECT * FROM (SELECT PAYS, ANNEE, MOIS, SUM(PORT) P

  2      FROM COMMANDES JOIN CLIENTS USING(CODE_CLIENT)

  3      WHERE (PAYS = ‘France’ AND MOIS < 3 ) OR

  4            (PAYS = ‘Finlande’ AND MOIS < 5 )

  5     GROUP BY PAYS, ANNEE, MOIS )

  6  MODEL RETURN UPDATED ROWS

  7  DIMENSION BY (PAYS, ANNEE, MOIS) MEASURES (P)

  8  RULES UPSERT ALL (

  9        P[ANY,2010,ANY] = 1 )

 10  ORDER BY 1,2,3;

PAYS          ANNEE       MOIS            P

——– ———- ———- ————

Finlande       2010          1            1

Finlande       2010          2            1

Finlande       2010          3            1

Finlande       2010          4            1

France         2010          1            1

France         2010          2            1

Les conditions

Il existe plusieurs types de conditions pouvant être utilisées dans les règles pour identifier la dimension ou la liste des dimensions correspondantes. Les premières conditions utilisées jusqu’à présent sont les conditions logiques simples que vous avez déjà rencontrées pour la clause « WHERE ».

SQL> WITH VMPP AS (

  2      SELECT NOM, PAYS, MOIS M, SUM(PORT) P

  3      FROM EMPLOYES JOIN COMMANDES USING (NO_EMPLOYE)

  4      WHERE ANNEE = 2011 AND NO_EMPLOYE IN (3,45,47,68)

  5      GROUP BY NOM, PAYS, MOIS )

  6  SELECT * FROM VMPP

  7  MODEL DIMENSION BY (NOM,PAYS,M)

  8  MEASURES (P P1,TO_NUMBER(NULL) P2,TO_NUMBER(NULL) P3,

  9  TO_NUMBER(NULL) P4,TO_NUMBER(NULL) P5,TO_NUMBER(NULL) P6,

 10  TO_NUMBER(NULL) P7)

 11  RULES (P2[ANY,PAYS IN (‘France’,’Suisse’),M > 3]= P1[CV(),CV(),CV()],

 12         P3[NOM LIKE ‘Le%’,ANY,M < 4]=P1[CV(),CV(),CV()],         

 13         P4[ANY,ANY,M BETWEEN 2 AND 4]=P1[CV(),CV(),CV()],

 14         P5[ANY,ANY,ANY]=AVG(P1)[CV(),CV(),M BETWEEN 1 AND 4],

 15         P6[ANY,ANY,ANY]=MIN(P1)[NOM LIKE ‘%re’,

 16            PAYS NOT IN (‘France’,’Suisse’),ANY],

 17         P7[ANY,PAYS > ‘Irlande’,ANY]=MAX(P1)[CV(),CV(),ANY])

 18  ORDER BY  NOM,PAYS,M;

NOM      PAYS     M     P1     P2     P3     P4     P5     P6     P7

——– ——- — —— —— —— —— —— —— ——

Dupouey  Irlande  1     71 —— —— ——    122    365 ——

Dupouey  Irlande  2    191 —— ——    191    122    365 ——

Dupouey  Irlande  3     58 —— ——     58    122    365 ——

Dupouey  Irlande  4    167 —— ——    167    122    365 ——

Dupouey  Irlande  5    262 —— —— ——    122    365 ——

Dupouey  Irlande  6    316 —— —— ——    122    365 ——

Gregoire France   1  2 002 —— —— ——  2 120    365 ——

Gregoire France   2  2 062 —— ——  2 062  2 120    365 ——

Gregoire France   3  2 274 —— ——  2 274  2 120    365 ——

Gregoire France   4  2 142  2 142 ——  2 142  2 120    365 ——

Gregoire France   5  2 612  2 612 —— ——  2 120    365 ——

Gregoire France   6  2 391  2 391 —— ——  2 120    365 ——

Lefebvre Suisse   1    226 ——    226 ——    232    365    471

Lefebvre Suisse   2    158 ——    158    158    232    365    471

Lefebvre Suisse   3    471 ——    471    471    232    365    471

Lefebvre Suisse   4     72     72 ——     72    232    365    471

Lefebvre Suisse   5    321    321 —— ——    232    365    471

Lefebvre Suisse   6    347    347 —— ——    232    365    471

Letertre Espagne  1    899 ——    899 ——    793    365 ——

Letertre Espagne  2    784 ——    784    784    793    365 ——

Letertre Espagne  3    365 ——    365    365    793    365 ——

Letertre Espagne  4  1 124 —— ——  1 124    793    365 ——

Letertre Espagne  5  1 031 —— —— ——    793    365 ——

Letertre Espagne  6    850 —— —— ——    793    365 ——

Il est également possible d’utiliser la fonction « CV » dans les conditions pour avoir un contrôle relatif à l’enregistrement courant.

SQL> WITH VMPP AS ( SELECT PAYS, MOIS M, SUM(PORT) P

  2      FROM EMPLOYES JOIN COMMANDES USING (NO_EMPLOYE)

  3      WHERE ANNEE = 2011 AND NO_EMPLOYE IN (3,45,47,68)

  4      GROUP BY PAYS, MOIS )

  5  SELECT * FROM VMPP MODEL DIMENSION BY (PAYS,M)

  6  MEASURES (P P1,TO_NUMBER(NULL) P2,TO_NUMBER(NULL) P3,

  7  TO_NUMBER(NULL) P4,TO_NUMBER(NULL) P5) RULES (

  8  P2[ANY,ANY]=MIN(P1)[CV(),M BETWEEN CV()-1 AND CV()+1],

  9  P3[ANY,ANY]=MAX(P1)[CV(),M BETWEEN CV()-1 AND CV()+1],

 10  P4[ANY,ANY]=P1[CV(),CV()]-P2[CV(),CV()],

 11  P5[ANY,ANY]=P1[CV(),CV()]-P3[CV(),CV()]) ORDER BY  PAYS,M;

PAYS     M     P1     P2     P3     P4     P5

——- — —— —— —— —— ——

Espagne  1    899    784    899    115      0

Espagne  2    784    365    899    419   -115

Espagne  3    365    365  1 124      0   -759

Espagne  4  1 124    365  1 124    759      0

Espagne  5  1 031    850  1 124    181    -93

Espagne  6    850    850  1 031      0   -181

France   1  2 002  2 002  2 062      0    -60

France   2  2 062  2 002  2 274     60   -212

France   3  2 274  2 062  2 274    212      0

France   4  2 142  2 142  2 612      0   -471

France   5  2 612  2 142  2 612    471      0

France   6  2 391  2 391  2 612      0   -221

Irlande  1     71     71    191      0   -120

Irlande  2    191     58    191    133      0

Irlande  3     58     58    191      0   -133

Irlande  4    167     58    262    110    -95

Irlande  5    262    167    316     95    -54

Irlande  6    316    262    316     54      0

Suisse   1    226    158    226     68      0

Suisse   2    158    158    471      0   -313

Suisse   3    471     72    471    399      0

Suisse   4     72     72    471      0   -399

Suisse   5    321     72    347    248    -26

Suisse   6    347    321    347     26      0

Une nouvelle condition « FOR … » est introduite uniquement dans la clause « MODEL » pour permettre de spécifier une liste des cellules à travers une dimension qui peuvent être modifiées ou ajoutées. Attention il n’est pas possible d’utiliser cette condition pour effectuer des calculs d’agrégats. La syntaxe est la suivante :

RULES (métrique[FOR dimension {IN({ expression[,…]|sous-requête})

  | FROM expression TO expression INCREMENT expression } ] [,…] )

sous-requête             La sous-requête ne peut pas être corrélée avec la requête principale. Vous ne pouvez pas utiliser une sous-requête déclarée dans une clause « WITH ». Elle ne doit pas retourner plus de 10 000 valeurs.

Voici dans l’exemple suivant l’utilisation de la condition « FOR » avec ses deux syntaxes : pour chacune des ces règles on affiche uniquement la valeur de la colonne P1 si la condition est validée ; dans la colonne P2 la condition n’est valable que pour les mois de janvier à mars mais uniquement pour les noms des pays > ‘Irlande’ ; la colonne P3 affiche les enregistrements uniquement tous les deux mois grâce à l’incrément ; la colonne P4 affiche uniquement les enregistrements pour les pays ‘France’ et ‘Suisse’ ; et finalement la colonne P5 affiche uniquement les enregistrements pour le pays du fournisseur du produit numéro 1.

SQL> WITH VMPP AS ( SELECT NOM, PAYS, MOIS M, SUM(PORT) P

  2      FROM EMPLOYES JOIN COMMANDES USING (NO_EMPLOYE)

  3      WHERE ANNEE = 2011 AND NO_EMPLOYE IN (1,45,47,68)

  4      GROUP BY NOM, PAYS, MOIS )

  5  SELECT * FROM VMPP

  6  MODEL DIMENSION BY (NOM,PAYS,M)

  7  MEASURES (P P1,TO_NUMBER(NULL) P2,TO_NUMBER(NULL) P3,

  8  TO_NUMBER(NULL) P4,TO_NUMBER(NULL) P5)

  9  RULES (P2[ANY,PAYS > ‘Irlande’,FOR M FROM 1 TO 3 INCREMENT 1]=

 10            P1[CV(),CV(),CV()],

 11         P3[ANY,ANY,FOR M FROM 1 TO 6 INCREMENT 2]=

 12            P1[CV(),CV(),CV()],

 13         P4[ANY,FOR PAYS IN (‘France’,’Suisse’),ANY]=

 14            P1[CV(),CV(),CV()],

 15         P5[ANY,FOR PAYS IN (SELECT PAYS FROM FOURNISSEURS

 16            NATURAL JOIN PRODUITS WHERE REF_PRODUIT = 1),ANY]=

 17            P1[CV(),CV(),CV()]) ORDER BY  PAYS,M;

NOM      PAYS         M     P1     P2     P3     P4     P5

——– ———– — —— —— —— —— ——

Gregoire France       1  2 002 ——  2 002  2 002 ——

Gregoire France       2  2 062 —— ——  2 062 ——

Gregoire France       3  2 274 ——  2 274  2 274 ——

Gregoire France       4  2 142 —— ——  2 142 ——

Gregoire France       5  2 612 ——  2 612  2 612 ——

Gregoire France       6  2 391 —— ——  2 391 ——

Dupouey  Irlande      1     71 ——     71 —— ——

Dupouey  Irlande      2    191 —— —— —— ——

Dupouey  Irlande      3     58 ——     58 —— ——

Dupouey  Irlande      4    167 —— —— —— ——

Dupouey  Irlande      5    262 ——    262 —— ——

Dupouey  Irlande      6    316 —— —— —— ——

Besse    Royaume-Uni  1  1 152  1 152  1 152 ——  1 152

Besse    Royaume-Uni  2  1 342  1 342 —— ——  1 342

Besse    Royaume-Uni  3    708    708    708 ——    708

Besse    Royaume-Uni  4  1 697 —— —— ——  1 697

Besse    Royaume-Uni  5    827 ——    827 ——    827

Besse    Royaume-Uni  6  1 251 —— —— ——  1 251

Lefebvre Suisse       1    226    226    226    226 ——

Lefebvre Suisse       2    158    158 ——    158 ——

Lefebvre Suisse       3    471    471    471    471 ——

Lefebvre Suisse       4     72 —— ——     72 ——

Lefebvre Suisse       5    321 ——    321    321 ——

Lefebvre Suisse       6    347 —— ——    347 ——

Les partitions

Vous pouvez également utiliser le partitionnement et alors les calculs suivant les dimensions et les métriques déclarés sont effectués uniquement dans une partition.

SQL> SELECT * FROM (SELECT ANNEE, MOIS, SUM(PORT) P FROM COMMANDES

  2      WHERE MOIS < 5 GROUP BY ANNEE, MOIS) SR

  3  MODEL PARTITION BY (ANNEE) DIMENSION BY (MOIS) MEASURES (P)

  4  RULES(P[5]=P[2]+P[3]) ORDER BY ANNEE, MOIS;

ANNEE  MOIS           P

—– —– ———–

 2010     1   49 332,80

 2010     2   46 707,10

 2010     3   49 768,40

 2010     4   46 904,00

 2010     5   96 475,50   <= 46 707,10 + 49 768,40

 2011     1   65 722,30

 2011     2   66 132,70

 2011     3   73 703,40

 2011     4   68 543,40

 2011     5  139 836,10   <= 66 132,70 + 73 703,40

Attention, une fois que vous avez initialisé le partitionnement, les règles mises en place sont exécutées pour toutes les partitions car la syntaxe d’adressage des métriques ne comporte pas la possibilité de cibler une cellule du tableau dans une autre partition que celle courante.

561.png

Dans l’exemple suivant, pour le métrique T on contrôle dans chaque partition que l’enregistrement du ’25/06/2011′ existe. S’il existe, la valeur du champ T est égale au champ P du même jour, sinon elle est égale au champ P du ’30/06/2011′.

SQL> WITH VMPQ AS (SELECT PAYS, DATE_COMMANDE D, SUM(PORT) P

  2      FROM CLIENTS JOIN COMMANDES USING (CODE_CLIENT)   

  3           JOIN DETAILS_COMMANDES USING (NO_COMMANDE)

  4      WHERE DATE_COMMANDE >= ’25/06/2011′

  5        AND PAYS IN (‘France’,’Brésil’,’Allemagne’)

  6        AND REF_PRODUIT = 1 GROUP BY PAYS, DATE_COMMANDE )

  7  SELECT * FROM VMPQ MODEL PARTITION BY (PAYS) DIMENSION BY (D)

  8  MEASURES (P,TO_NUMBER(NULL) T, TO_NUMBER(NULL) C)

  9  RULES ( T[’25/06/2011′]=

 10             CASE WHEN P[’25/06/2011′] IS PRESENT

 11             THEN P[’25/06/2011′] ELSE P[’30/06/2011′] END,

 12          C[’30/06/2011′] = SUM(P)[ANY]) ORDER BY 1,2,3;

PAYS        D               P      T      C

———– ———- —— —— ——

Allemagne   25/06/2011   99,7   99,7 ——    <= P[’25/06/2011′]

Allemagne   26/06/2011   93,4 —— ——

Allemagne   28/06/2011  165,7 —— ——

Allemagne   30/06/2011  119,5 ——  478,3

Brésil      25/06/2011 ——  149,4 ——    <= P[’30/06/2011′]

Brésil      28/06/2011   91,5 —— ——

Brésil      29/06/2011   91,2 —— ——

Brésil      30/06/2011  149,4 ——  332,1

France      25/06/2011 ——   93,0 ——    <= P[’30/06/2011′]

France      26/06/2011   76,1 —— ——

France      27/06/2011   57,9 —— ——

France      28/06/2011  178,8 —— ——

France      30/06/2011   93,0 ——  405,8

La requête suivante permet d’afficher la somme des frais de port par année, par mois et par pays qui est le critère de partitionnement. La première règle permet de calculer la somme des frais de port pour l’ensemble du pays et de l’afficher dans la colonne T pour un nouveau mois 4, inséré pour chaque année de la partition. La deuxième règle permet de calculer de nouveau la somme des frais de port pour l’ensemble de la partition et de l’afficher dans la colonne P pour une nouvelle année 2012 et un nouveau mois 4.

SQL> SELECT * FROM ( SELECT PAYS, ANNEE, MOIS, SUM(PORT) P

  2      FROM CLIENTS JOIN COMMANDES USING (CODE_CLIENT)

  3           JOIN DETAILS_COMMANDES USING (NO_COMMANDE)

  4      WHERE PAYS IN (‘France’,’Brésil’) AND REF_PRODUIT = 1

  5        AND MOIS BETWEEN 1 AND 3 GROUP BY PAYS, ANNEE, MOIS)

  6  MODEL PARTITION BY (PAYS) DIMENSION BY (ANNEE,MOIS)

  7  MEASURES (P,TO_NUMBER(NULL) T) RULES UPSERT ALL

  8  ( T[ANY ,4] = SUM(P)[ANY,ANY], P[2012,4] = SUM(P)[ANY,ANY])

  9  ORDER BY PAYS, ANNEE, MOIS;

PAYS        ANNEE       MOIS       P       T

———– —– ———- ——- ——-

Brésil       2010          1   1 740 ——-

Brésil       2010          2     730 ——-

Brésil       2010          3   1 363 ——-

Brésil       2010          4 ——-   9 378       <=  T[ANY ,4]

Brésil       2011          1   1 328 ——-

Brésil       2011          2   2 077 ——-

Brésil       2011          3   2 140 ——-

Brésil       2011          4 ——-   9 378       <=  T[ANY ,4]

Brésil       2012          4   9 378 ——-       <=  P[ANY ,4]

France       2010          1   2 145 ——-

France       2010          2   1 385 ——-

France       2010          3   1 459 ——-

France       2010          4 ——-  10 963       <=  T[ANY ,4]

France       2011          1   1 709 ——-

France       2011          2   1 823 ——-

France       2011          3   2 443 ——-

France       2011          4 ——-  10 963       <=  T[ANY ,4]

France       2012          4  10 963 ——-       <=  P[ANY ,4]

Dans l’exemple suivant la colonne comporte deux règles. La première permet de calculer la somme des quantités vendues de la catégorie du produit pour l’année en cours affichée pour le trimestre 5. La deuxième est d’insérer un enregistrement pour chaque trimestre dans une nouvelle année 2012 affichant la somme du même trimestre des années 2010 et 2011.

SQL> WITH CATQ AS ( SELECT NOM_CATEGORIE CATEGORIE, ANNEE A,

  2     TRIMESTRE T,SUM(DC.QUANTITE) Q

  3     FROM CLIENTS CL NATURAL JOIN COMMANDES CO

  4     NATURAL JOIN DETAILS_COMMANDES DC JOIN PRODUITS

  5     USING(REF_PRODUIT) JOIN CATEGORIES USING(CODE_CATEGORIE)

  6  WHERE NO_EMPLOYE IN (45) AND CODE_CATEGORIE < 4

  7  GROUP BY NOM_CATEGORIE, ANNEE, TRIMESTRE)

  8  SELECT * FROM CATQ MODEL PARTITION BY (CATEGORIE)

  9  DIMENSION BY (A, T) MEASURES (Q) RULES UPSERT ALL

 10  ( Q[ANY,5] = SUM(Q)[CV(),ANY], Q[2012,ANY] = SUM(Q)[ANY,CV()])

 11  ORDER BY CATEGORIE, A, T;

CATEGORIE        A   T        Q

———— —– — ——–

Boissons      2010   1   30 323

Boissons      2010   2   32 897

Boissons      2010   3   31 088

Boissons      2010   4   28 987

Boissons      2010   5  123 295 <= 30 323 + 32 897 + 31 088 + 28 987

Boissons      2011   1   47 250

Boissons      2011   2   51 112

Boissons      2011   5   98 362

Boissons      2012   1   77 573 <= 30 323 + 47 250

Boissons      2012   2   84 009

Boissons      2012   3   31 088

Boissons      2012   4   28 987

Boissons      2012   5  221 657

Condiments    2010   1   37 368

Condiments    2010   2   42 000

Condiments    2010   4   40 009

Condiments    2010   5  159 369

Les valeurs NULL

Vous pouvez configurer la gestion de la cohérence des valeurs traitées par la clause à l’aide de la syntaxe suivante :  MODEL [{ IGNORE | KEEP } NAV ]

IGNORE NAV                  L’option permet de remplacer toutes les valeurs NULL ou manquantes et renvoyer une valeur suivant le type de la colonne : « 0 » pour les données de type numérique, « 01/01/2000 » pour les données de type date, une chaîne vide pour les données de type caractère et NULL pour les autres.

KEEP NAV                      L’option ne traite pas les valeurs NULL, c’est option par défaut.

SQL> WITH

  2  VENTES AS ( SELECT DATE_COMMANDE, SUM(PORT) SP FROM COMMANDES

  3              WHERE DATE_COMMANDE BETWEEN ’07/05/2011′ AND ’08/05/2011′

  4                AND CODE_CLIENT IN (‘CHOPS’) GROUP BY DATE_COMMANDE),

  5  VF AS (   SELECT JOUR, SP FROM VENTES V RIGHT OUTER JOIN  

  6                 ( SELECT JOUR FROM DIM_TEMPS

  7                   WHERE JOUR BETWEEN ’07/05/2011′ AND ’08/05/2011′) T 

  8            ON ( V.DATE_COMMANDE = T.JOUR)), 

  9  M01 AS ( SELECT * FROM VF    

 10      MODEL IGNORE NAV DIMENSION BY (JOUR) MEASURES (SP)

 11      RULES( SP[’09/05/2011′]= SP[’07/05/2011′]+SP[’08/05/2011′])),

 12  M02 AS ( SELECT * FROM VF          

 13      MODEL KEEP NAV RETURN UPDATED ROWS

 14      DIMENSION BY (JOUR) MEASURES (SP)

 15      RULES( SP[’09/05/2011′]= SP[’07/05/2011′]+SP[’08/05/2011′])),

 16  M03 AS ( SELECT * FROM VF          

 17      MODEL RETURN UPDATED ROWS

 18      DIMENSION BY (JOUR) MEASURES (SP)

 19      RULES( SP[’09/05/2011′]= NVL(SP[’07/05/2011′],0)+

 20         NVL(SP[’08/05/2011′],0)))

 21  SELECT ‘MODEL IGNORE NAV’, M01.* FROM M01        UNION ALL

 22  SELECT ‘MODEL KEEP NAV  ‘, M02.* FROM M02        UNION ALL

 23  SELECT ‘MODEL DEFAUT+NVL’, M03.* FROM M03;

‘MODELIGNORENAV’ JOUR               SP

—————- ———- ———-

MODEL IGNORE NAV 08/05/2011       54,5

MODEL IGNORE NAV 07/05/2011 ———-

MODEL IGNORE NAV 09/05/2011       54,5

MODEL KEEP NAV   09/05/2011 ———-

MODEL DEFAUT+NVL 09/05/2011       54,5

Dans l’exemple précédent, il y a trois sous-requêtes : la première affiche tous les enregistrements et les deux dernières uniquement les enregistrements modifiés. La première sous-requête utilise l’option « IGNORE NAV », ainsi la somme des deux valeurs numériques n’est pas NULL comme pour la deuxième sous-requête. La dernière traite la valeur NULL avec la fonction « NVL ».

PRESENTV

La fonction renvoie la première expression si la cellule existe avant l’exécution de la clause « MODEL », sinon elle renvoie la deuxième expression. La syntaxe de la fonction est :

PRESENTV ( référence cellule, expression, expression )

PRESENTNNV

La fonction renvoie la première expression si la cellule existe avant l’exécution de la clause « MODEL » et si sa valeur n’est pas NULL, sinon elle renvoie la deuxième expression. La syntaxe de la fonction est :

PRESENTNNV ( référence cellule, expression, expression )

SQL> WITH VENTES AS ( SELECT CL.PAYS, CO.DATE_COMMANDE, SUM(CO.PORT) P

  2                   FROM CLIENTS CL JOIN COMMANDES CO   

  3                  ON ( CL.CODE_CLIENT = CO.CODE_CLIENT

  4             AND CO.DATE_COMMANDE BETWEEN ’05/05/2011′ AND ’10/05/2011′

  5             AND CL.CODE_CLIENT IN (‘FOLIG’,’ROMEY’, ‘CHOPS’))

  6              GROUP BY CL.PAYS, CO.DATE_COMMANDE),

  7  VF AS ( SELECT PAYS, JOUR, P FROM VENTES V

  8     PARTITION BY (PAYS) RIGHT OUTER JOIN( SELECT JOUR FROM DIM_TEMPS

  9                  WHERE JOUR BETWEEN ’05/05/2011′ AND ’10/05/2011′) T

 10     ON ( V.DATE_COMMANDE = T.JOUR))

 11  SELECT * FROM VF MODEL PARTITION BY (PAYS) DIMENSION BY (JOUR) 

 12  MEASURES ( P, 0 PV, 0 PNNV, 0 PNVL)

 13  RULES ( PV  [ANY]=PRESENTV(P[CV()],P[CV()]*1.1,0),

 14          PNNV[ANY]=PRESENTNNV(P[CV()],P[CV()]*1.1,0),

 15          PNVL[ANY]=NVL(PRESENTV(P[CV()],P[CV()]*1.1,0),0))ORDER BY 1,2;

PAYS    JOUR             P      PV    PNNV    PNVL

——- ———- ——- ——- ——- ——-

Espagne 05/05/2011   62,30   68,53   68,53   68,53

Espagne 06/05/2011   69,90   76,89   76,89   76,89

Espagne 07/05/2011   59,00   64,90   64,90   64,90

Espagne 08/05/2011 ——- ——-     ,00     ,00

Espagne 09/05/2011 ——- ——-     ,00     ,00

Espagne 10/05/2011 ——- ——-     ,00     ,00

France  05/05/2011   60,10   66,11   66,11   66,11

France  06/05/2011   66,60   73,26   73,26   73,26

L’exécution des règles

Les règles peuvent être exécutées séquentiellement, l’option par défaut, ou dans l’ordre de leurs dépendances suivant les calculs effectués. La syntaxe qui permet de préciser le mode d’interprétation est la suivante :

RULES [{ AUTOMATIC | SEQUENTIAL } ORDER ] …

Dans le cas de l’exécution des calculs séquentiellement, vous devez, pour la cohérence, tenir compte de l’antériorité des calculs. Dans l’exemple suivant, pour la colonne P1 trois règles de calcul sont décrites pour trois nouveaux enregistrements pour chaque année.

SQL> SELECT * FROM ( SELECT ANNEE, MOIS, SUM(PORT) P1

  2  FROM COMMANDES WHERE NO_EMPLOYE = 12 GROUP BY ANNEE, MOIS)

  3  MODEL DIMENSION BY (ANNEE,MOIS)

  4  MEASURES(P1) RULES UPSERT ALL SEQUENTIAL ORDER (

  5  P1[ANY,13] =SUM(P1)[CV(),ANY],

La première calcule la somme des frais de port pour la même année et l’affiche dans un nouveau mois 13.

  6  P1[ANY,0]  =SUM(P1)[CV(),MOIS BETWEEN 1 AND 6],

La deuxième calcule la somme des frais de port uniquement pour les premiers six mois de la même année et l’affiche dans un nouveau mois 0.

  7  P1[2011,13]=P1[CV()-1,CV()])ORDER BY ANNEE, MOIS;

La troisième règle affiche dans un nouvel enregistrement pour l’année 2011 et le mois 13 la valeur du même mois de l’année précédente.

ANNEE MOIS        P1

—– —- ———

 2010    0  4 146,90

 2010    1    661,00

 2010    2    424,40

 2010    3    467,60

 2010    4    677,50

 2010    5    742,80

 2010    6  1 173,60

 2010    7    676,30

 2010    8    416,70

 2010    9    811,30

 2010   10    543,70

 2010   11  1 410,60

 2010   12    877,90

 2010   13  8 883,40

 2011    0  4 794,70

 2011    1    956,70

 2011    2    744,40

 2011    3    662,10

 2011    4    877,40

 2011    5    912,60

 2011    6    641,50

 2011   13  8 883,40

Dans cet exemple, l’ordre séquentiel est salutaire car il nous permet de calculer le mois 0 la somme des frais de port pour les premiers six mois, mais cette somme n’est pas prise en compte pour la somme des frais de port de l’année.

Dans le cas ou vous utilisez « AUTOMATIC ORDER », l’interprétation est effectuée tenant compte des dépendances des cellules, ainsi il calcule d’abord toutes les cellules indépendantes et ensuite tous les calculs qui utilisent ces cellules. Attention, dans ce cas une cellule ne peut être mise à jour qu’une seule fois.

SQL> SELECT * FROM ( SELECT ANNEE, MOIS, SUM(PORT) P1

  2                  FROM COMMANDES GROUP BY ANNEE, MOIS)

  3  MODEL DIMENSION BY (ANNEE,MOIS) MEASURES(P1)

  4  RULES UPSERT ALL AUTOMATIC ORDER (

  5  P1[ANY,13] =SUM(P1)[CV(),ANY],P1[2011,13]=P1[CV()-1,CV()]);

P1[ANY,13] =SUM(P1)[CV(),ANY],P1[2011,13]=P1[CV()-1,CV()])

                              *

ERREUR à la ligne 5 :

ORA-32630: plusieurs affectations en ordre automatique MODEL

Dans l’exemple suivant, le même ensemble de règles est exécuté deux fois avec les deux options « AUTOMATIC » et « SEQUENTIAL » pour voir la différence de calcul des ces deux options.

SQL> WITH

  2  CATQ AS(SELECT NOM_CATEGORIE C, TRIMESTRE T, SUM(DC.QUANTITE) Q

  3     FROM CLIENTS CL NATURAL JOIN COMMANDES CO

  4     NATURAL JOIN DETAILS_COMMANDES DC JOIN PRODUITS

  5     USING(REF_PRODUIT) JOIN CATEGORIES USING(CODE_CATEGORIE)

  6     WHERE NO_EMPLOYE = 1 AND ANNEE = 2010

  7       AND CODE_CATEGORIE IN (6,8,10) GROUP BY NOM_CATEGORIE, TRIMESTRE)

  8  SELECT ‘A’,C CATEGORIE,T,Q0,Q FROM CATQ MODEL  

  9  DIMENSION BY (C, T) MEASURES (Q Q0,Q)    

 10  RULES UPSERT ALL AUTOMATIC ORDER (

 11  Q[‘x–Toutes Viandes–x’,ANY]   =SUM(Q)[C LIKE ‘Viande%’,CV()],  <-  6

 12  Q[‘x–Toutes–x’,ANY]           =AVG(Q)[ANY,CV()],               <-  7

 13  Q[‘Viande en conserve’,4]       =Q[CV(),1]+Q[CV(),3],            <-  3

 14  Q[‘Viandes’,4]                  =Q[CV(),2]+Q[CV(),3],            <-  5

 15  Q[‘Viande en conserve’,1]       =AVG(Q)[CV(),T IN (2,3)],        <-  2

 16  Q[‘Viandes’,2]                  =AVG(Q)[CV(),T IN (1,3)],        <-  4

 17  Q[‘Poissons et fruits de mer’,3]=Q[CV(),1]+Q[CV(),2])            <-  1

 18  UNION ALL

 19  SELECT ‘S’,C CATEGORIE,T,Q0,Q FROM CATQ MODEL

 20  DIMENSION BY (C, T) MEASURES (Q Q0,Q)

 21  RULES UPSERT ALL SEQUENTIAL ORDER (

 22  Q[‘x–Toutes Viandes–x’,ANY]   =SUM(Q)[C LIKE ‘Viande%’,CV()],

 23  Q[‘x–Toutes–x’,ANY]           =AVG(Q)[ANY,CV()],

 24  Q[‘Viande en conserve’,4]       =Q[CV(),1]+Q[CV(),3],

 25  Q[‘Viandes’,4]                  =Q[CV(),2]+Q[CV(),3],

 26  Q[‘Viande en conserve’,1]       =AVG(Q)[CV(),T IN (2,3)],

 27  Q[‘Viandes’,2]                  =AVG(Q)[CV(),T IN (1,3)],

 28  Q[‘Poissons et fruits de mer’,3]=Q[CV(),1]+Q[CV(),2])

 29  ORDER BY 1 DESC,2,3;

‘ CATEGORIE                   T       Q0        Q

– ————————- — ——– ——–

S Poissons et fruits de mer   1   17 384   17 384

S Poissons et fruits de mer   2    8 421    8 421

S Poissons et fruits de mer   3   11 641   25 805 <= 17 384 + 8 421

S Poissons et fruits de mer   4   15 161   15 161

S Viande en conserve          1    4 237    2 560

S Viande en conserve          2    2 590    2 590

S Viande en conserve          3    2 530    2 530

S Viande en conserve          4    3 325    6 767 <= 4 237 + 2 530

S Viandes                     1    8 673    8 673

S Viandes                     2    5 616    7 478

S Viandes                     3    6 283    6 283

S Viandes                     4    6 253   11 899 <= 5 616 + 6 283

S x–Toutes Viandes–x        1 ——–   12 910

S x–Toutes Viandes–x        2 ——–    8 206

S x–Toutes Viandes–x        3 ——–    8 813

S x–Toutes Viandes–x        4 ——–    9 578 <= 6 253 + 3 325

S x–Toutes–x                1 ——–   10 801

S x–Toutes–x                2 ——–    6 208

S x–Toutes–x                3 ——–    7 317

S x–Toutes–x                4 ——–    8 579

A Poissons et fruits de mer   1   17 384   17 384

A Poissons et fruits de mer   2    8 421    8 421

A Poissons et fruits de mer   3   11 641   25 805

A Poissons et fruits de mer   4   15 161   15 161

A Viande en conserve          1    4 237    2 560

A Viande en conserve          2    2 590    2 590

A Viande en conserve          3    2 530    2 530

A Viande en conserve          4    3 325    5 090 <= 2 560 + 2 530

A Viandes                     1    8 673    8 673

A Viandes                     2    5 616    7 478

A Viandes                     3    6 283    6 283

A Viandes                     4    6 253   13 761 <= 7 478 + 6 283

A x–Toutes Viandes–x        1 ——–   11 233

A x–Toutes Viandes–x        2 ——–   10 068

A x–Toutes Viandes–x        3 ——–    8 813

A x–Toutes Viandes–x        4 ——–   18 851 <= 13 761 + 5 090

A x–Toutes–x                1 ——–    9 963

A x–Toutes–x                2 ——–    7 139

A x–Toutes–x                3 ——–   10 858

A x–Toutes–x                4 ——–   13 216

Une autre erreur que vous pouvez avoir avec l’option « AUTOMATIC ORDER », est de calculer plusieurs cellules avec une formule récursive qui fait appel aux mêmes cellules.

SQL> SELECT * FROM ( SELECT ANNEE, MOIS, SUM(PORT) P1

  2                  FROM COMMANDES GROUP BY ANNEE, MOIS)

  3  MODEL DIMENSION BY (ANNEE,MOIS) MEASURES(P1)

  4  RULES UPSERT ALL AUTOMATIC ORDER(P1[ANY,12]=SUM(P1)[CV(),ANY]);

                FROM COMMANDES GROUP BY ANNEE, MOIS)

                     *

ERREUR à la ligne 2 :

ORA-32634: l’évaluation MODEL avec ordre automatique ne converge pas

L’itération des règles

Les règles peuvent être exécutées une seule fois ou plusieurs fois à l’aide de l’opération « ITERATE ». La mise en œuvre de cette opération est possible à l’aide de la syntaxe :

RULES ITERATE ( valeur numérique ) [ UNTIL condition de sortie ]

Dans la clause « MODEL » vous bénéficiez de la possibilité de connaître le niveau de l’itération à l’aide de la pseudo-colonne « ITERATION_NUMBER » qui renvoie 0 à la première itération puis, pour les itérations suivantes, un entier qui représente le nombre d’itérations.

L’exemple suivant permet d’ajouter les prévisions des sommes de frais de port en augmentant de 10% chaque année la        valeur de l’année précédente. La colonne I représente le niveau de l’itération retournée par la pseudo-colonne « ITERATION_NUMBER ».

SQL> WITH

  2  VENTES AS (

  3      SELECT PAYS, ANNEE, SUM(PORT) P

  4      FROM CLIENTS CL NATURAL JOIN COMMANDES

  5      WHERE PAYS IN (‘Espagne’,’France’)

  6      AND ANNEE = 2011 GROUP BY PAYS, ANNEE)

  7  SELECT * FROM VENTES

  8  MODEL PARTITION BY (PAYS) DIMENSION BY (ANNEE)

  9  MEASURES (P,TO_NUMBER(NULL) I)

 10  RULES SEQUENTIAL ORDER ITERATE (3)

 11  ( P[2011+ITERATION_NUMBER+1]=P[2011+ITERATION_NUMBER]*1.1,

 12    I[2011+ITERATION_NUMBER+1]=ITERATION_NUMBER)

 13  ORDER BY 1,2;

PAYS                 ANNEE           P          I

————— ———- ———– ———-

Espagne               2011   23 539,00 ———-

Espagne               2012   25 892,90          0

Espagne               2013   28 482,19          1

Espagne               2014   31 330,41          2

France                2011   52 583,90 ———-

France                2012   57 842,29          0

France                2013   63 626,52          1

France                2014   69 989,17          2

Une nouvelle fonction « PREVIOUS » permet d’écrire des conditions plus cohérentes dans l’option « UNTIL ». L’utilisation de cette fonction est admise uniquement à cet emplacement avec la syntaxe suivante :

UNTIL ( PREVIOUS ( référence_cellule ) … )

SQL> WITH

  2  VENTES AS (

  3      SELECT PAYS, ANNEE, SUM(PORT) P

  4      FROM CLIENTS CL NATURAL JOIN COMMANDES

  5      WHERE PAYS IN (‘Espagne’,’France’)

  6      AND ANNEE = 2011 GROUP BY PAYS, ANNEE)

  7  SELECT * FROM VENTES

  8  MODEL PARTITION BY (PAYS) DIMENSION BY (ANNEE)

  9  MEASURES (P,TO_NUMBER(NULL) I)

 10  RULES ITERATE (1000)

 11  UNTIL( PREVIOUS(P[2011+ITERATION_NUMBER+1])-P[2011]> 20000

 12         OR 2011+ITERATION_NUMBER+1 >= 2017)

 13  ( P[2011+ITERATION_NUMBER+1]=P[2011+ITERATION_NUMBER]*1.1,

 14    I[2011+ITERATION_NUMBER+1]=ITERATION_NUMBER)

 15  ORDER BY 1,2;

PAYS    ANNEE           P    I

——- —– ———– —-

Espagne  2011   23 539,00 —-

Espagne  2012   25 892,90    0

Espagne  2013   28 482,19    1

Espagne  2014   31 330,41    2

Espagne  2015   34 463,45    3

Espagne  2016   37 909,79    4

Espagne  2017   41 700,77    5 <= 41 700,77 – 23 539,00 < 20 000

France   2011   52 583,90 —-                     ANNEE = 2017

France   2012   57 842,29    0

France   2013   63 626,52    1

France   2014   69 989,17    2 <= 69 989,17 – 52 583,90 < 20 000

France   2015   76 988,09    3 <= 76 988,09 – 52 583,90 > 20 000

Dans l’exemple suivant, l’itération est exécutée tant que la limite maximum n’est pas atteinte où le prédicat déclaré dans l’option « UNTIL » est VRAI. Le prédicat contrôle que la valeur de la différence de l’année précédente et de la première occurrence est inférieure à 20 000 ou l’année en cours est au maximum 2017.

Vous pouvez utiliser les itérations pour effectuer le calcul et l’afficher dans la même cellule.

SQL> SELECT * FROM (SELECT 1 DIM,1000 M FROM DUAL)

  2  MODEL DIMENSION BY (DIM) MEASURES ( M, M1, 0 I)

  3  RULES SEQUENTIAL ORDER ITERATE (1000)

  4  UNTIL ( PREVIOUS(M[1]) – M[1] < 100)

  5  (M[1] = M[1]/4,

  6   I[1+ITERATION_NUMBER+1]=ITERATION_NUMBER+1,

  7   M1[1+ITERATION_NUMBER+1]=M1[1+ITERATION_NUMBER]/4);

DIM         M        M1     I

— ——— ——— —–

  1     15,63  1 000,00     0

  2 ———    250,00     1

  3 ———     62,50     2

  4 ———     15,63     3

L’assemblage des modèles

Il est possible de combiner plusieurs modèles références dans un modèle principal. Dans la syntaxe, on commence par déclarer les modèles références et ensuite le modèle principal. Il est obligatoire que chaque modèle référence soit utilisé au moins dans une des règles. Attention, au niveau d’utilisation de la fonction « CV » pour qu’elle trouvé la valeur de la dimension elle à impérativement besoin du nom de la dimension. La syntaxe de déclarations des modèles références est :

SELECT … MODEL

 [ REFERENCE nom_du_modèle on (sous-requête) [,…]]

 [ MAIN nom_du_modèle ]…

STAG01@topaze> WITH

  2   VENTES AS (

  3    SELECT PAYS PP,ANNEE AP,TRIMESTRE TP,SUM(PRIX_UNITAIRE*QUANTITE) CA,

  4              SUM(QUANTITE) Q

  5       FROM CLIENTS NATURAL JOIN COMMANDES

  6                    NATURAL JOIN DETAILS_COMMANDES

  7       WHERE ANNEE = 2010 AND PAYS IN (‘Italie’,’France’,’Suisse’)

  8       GROUP BY PAYS,ANNEE,TRIMESTRE),

  9   FRAIS AS (

 10       SELECT PAYS PR,ANNEE AR,TRIMESTRE TR,SUM(PORT) SP

 11       FROM CLIENTS NATURAL JOIN COMMANDES

 12       WHERE ANNEE = 2010 AND PAYS IN (‘Italie’,’France’,’Suisse’)

 13       GROUP BY PAYS,ANNEE,TRIMESTRE)

 14   SELECT * FROM VENTES

 15   MODEL

 16   REFERENCE frais

 17       ON (SELECT * FROM FRAIS)

 18       DIMENSION BY (PR,AR,TR) MEASURES (SP) IGNORE NAV

 19   MAIN ventes

 20       DIMENSION BY (PP,AP,TP) MEASURES (CA,Q,0 SP1,CA NCA)

 21       RULES(

 22              SP1[ANY,ANY,ANY] =

 23                             frais.SP[CV(PP),CV(AP),CV(TP)],

 24               NCA[ANY,ANY,ANY]=CA[CV(),CV(),CV()] –

 25                  frais.SP[CV(PP),CV(AP),CV(TP)])

 26   ORDER BY 1,2,3;

PP          AP  TP             CA        Q           SP1            NCA

——– —– — ————– ——– ————- ————–

France    2010   1  60 767 879,64  928 929     17 814,70  60 750 064,94

France    2010   2  61 776 341,04  940 449     18 714,90  61 757 626,14

France    2010   3  61 218 497,16  933 988     18 285,00  61 200 212,16

France    2010   4  60 711 312,36  927 487     17 989,60  60 693 322,76

Italie    2010   1  14 415 191,28  220 434      4 316,90  14 410 874,38

Italie    2010   2  13 984 922,88  211 007      4 196,20  13 980 726,68

Italie    2010   3  14 995 751,40  226 536      4 287,70  14 991 463,70

Italie    2010   4  15 223 098,36  233 658      4 697,10  15 218 401,26

Suisse    2010   1   9 525 672,48  145 357      2 824,60   9 522 847,88

Suisse    2010   2  12 891 916,68  196 279      3 659,80  12 888 256,88

Suisse    2010   3  13 508 505,72  205 786      4 106,10  13 504 399,62

Suisse    2010   4   9 081 987,72  139 178      2 672,30   9 079 315,42

 


Références: http://db-experts.com

Categories: Base de données

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *