Qlik Community

Groupe des Utilisateurs Francophones

Announcements
June 28, 10AM ET: Qlik Nation and Qlik Community present: CyberSleuth REGISTER TODAY
cancel
Showing results for 
Search instead for 
Did you mean: 
Not applicable

Modélisation en étoiles avec 2 tables de fait

Bonjour,

Voici ma structure :

1 table "dimension" CLIENT :

"N° client"

"Secteur"

"Nom"

"prénom"

....

1 table "dimension" PRODUIT :

"Ref"

"Désignation"

"groupe produit"

....

1 table "dimension" CALENDRIER

"date"

"mois"

"année"

....

puis,

1 table "de fait" FACTURE :

"N° client"

"date"

"Ref"

"Qte facture"

"Montant facture"

.....

1 table "de fait" AVOIR :

"N° client"

"date"

"Ref"

"Qte facture"

"Montant facture"

......

Mon objectif : c'est de calculer le CA net 'facture - avoir' en fonction d'une classification Client et/ou Produits et en fonction du temps.

Problème : En faisant cette structure qlikview me génère un cycle donc ça ne va pas

Merci d'avance pour vos remarques et analyses

Mathieu

1 Solution

Accepted Solutions
rlp
Creator
Creator

Il vous faut enlever le QUALIFY * et le UNQUALIFY "KEY_*" puisque avec la méthode Link_Table, vous n'aurez plus de boucles.

De même, n renommer pas les champs :

REF en KEY_REF

et

[N° client] en KEY_client

Cela donne le code suivant:

// Idem Original


//---------------------------------------------------------------------------------------------//LET vDateMin = Num(MakeDate(2010,1,1));LET vDateMax = Num(MakeDate(2015,1,1));//Floor(YearEnd(AddMonths(Today(), 12)));LET vDateToday = Num(Today());

TempCalendar:LOAD$(vDateMin) + RowNo() - 1 AS DateNumber,Date($(vDateMin) + RowNo() - 1) AS TempDateAUTOGENERATE 1WHILE $(vDateMin)+IterNo()-1<= $(vDateMax);

MasterCalendar:LOADTempDate as KEY_date,Day(TempDate) AS Day,Month(TempDate) AS Month,Year(TempDate) AS Year,Today() as DayNowRESIDENT TempCalendar ORDER BY TempDate ASC;
DROP TABLE TempCalendar;
LET vDateMin = Num(MakeDate(2010,1,1));LET vDateMax = Num(MakeDate(2015,1,1));//Floor(YearEnd(AddMonths(Today(), 12)));LET vDateToday = Num(Today());

// Suppression des QUALIFY et UNQUALIFY

// Chargement initial sans renommage

CLIENT :LOAD [N° client] , // AS KEY_client,
    
ZoneFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is client$);

PRODUIT :LOAD REF , // , as KEY_REF,
    
GROUPEFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is produit$);

AVOIR :LOAD

     //,
    
[N° client],
    
REF,
    
QTE,
    
DATEFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is Avoir$);

FACTURE :LOAD

     // ,
    
[N° client],
    
REF,
    
QTE,
    
DATE FROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is Facture$);

/ /Création de la Link_Table => Code du premier post

// Elimination des doublons propres à FACTURE

tmp_Link_Table:

NoConcatenate

LOAD DISTINCT

     [N° client] ,

     date ,

     ref

RESIDENT FACTURE ;

// ELimination des doublons propres à AVOIR

Concatenate( tmp_Link_Table )

LOAD DISTINCT

     [N° client] ,

     date ,

     ref

RESIDENT AVOIR ;

// Elimination des doublons dus aux combinaisons

// présentes dans les deux tables de fait

Link_Table :

NoConcatenate

LOAD DISTINCT

     *

RESIDENT tmp_Link_Table ;

DROP TABLE tmp_Link_Table ;

FOR EACH table IN 'FACTURE' , 'AVOIR' , 'Link_Table'

     LEFT JOIN( $(table)

     LOAD

               // champs_de_jointure

              [N° client] ,

               date ,

               ref

               //clé additionnelle

               [N° client] & '|&|' & date & '|&|' & ref as clé

     RESIDENT $(table) ;

     // On ne garde les champs problématiques que dans la Link_Table

     IF '$(table)' <> 'Link_Table' THEN

          DROP FIELDS [N° client] , date , ref FROM $(table) ;

     ENDIF

NEXT table ;


Ce message a été modifié par: Richard Pressanti: Oubli d'une virgule

View solution in original post

16 Replies
rlp
Creator
Creator

Il vous faut créer une table de liens (en anglais Link Table) centrale qui assurera la connexion avec vos deux tables de faits et vos tables de dimensions.

Concrétement, votre table de liens contiendra vos 3 champs problématiques qui devront donc être supprimés des tables de fait. Tout le problème est de récupérer toutes les combianaisins distinctes de vos deux tables de liens.

Le code suivant devrait fonctionner.

// Elimination des doublons propres à FACTURE

tmp_Link_Table:

NoConcatenate

LOAD DISTINCT

     [N° client] ,

     date ,

     ref

RESIDENT FACTURE ;

// ELimination des doublons propres à AVOIR

Concatenate( tmp_Link_Table )

LOAD DISTINCT

     [N° client] ,

     date ,

     ref

RESIDENT AVOIR ;

// Elimination des doublons dus aux combinaisons

// présentes dans les deux tables de fait

Link_Table :

NoConcatenate

LOAD DISTINCT

     *

RESIDENT tmp_Link_Table ;

DROP TABLE tmp_Link_Table ;

FOR EACH table IN 'FACTURE' , 'AVOIR' , 'Link_Table'

     LEFT JOIN( $(table) )

     LOAD

               // champs_de_jointure

              [N° client] ,

               date ,

               ref ,

               //clé additionnelle

               [N° client] & '|&|' & date & '|&|' & ref as clé

     RESIDENT $(table) ;

     // On ne garde les champs problématiques que dans la Link_Table

     IF '$(table)' <> 'Link_Table' THEN

          DROP FIELDS [N° client] , date , ref FROM $(table) ;

     ENDIF

NEXT table ;

Ce message a été modifié par: Richard Pressanti: Correction d'erreurs de frappe.

Ce message a été modifié par: Richard Pressanti: Ajout d'une parenthèse manquante

Ce message a été modifié par: Richard Pressanti: Ajout d'une virgule manquante

Not applicable
Author

Bonjour,

Merci de votre retour et pour le code.

Ok pour passer par une table de lien. Passer par une concatenation de mes 2 tables de fait est également une solution?

Par rapport au code :

J'ai un message d'erreur au chargement des données :

Champ introuvable - <N°>
tmp_Link_Table:

NoConcatenate
LOAD DISTINCT
  N°,
     [N° client],
     REF,
     QTE,
     DATE
RESIDENT FACTURE

Ci dessous le code que j'utilise :

//---------------------------------------------------------------------------------------------//LET vDateMin = Num(MakeDate(2010,1,1));LET vDateMax = Num(MakeDate(2015,1,1));//Floor(YearEnd(AddMonths(Today(), 12)));LET vDateToday = Num(Today());

TempCalendar:LOAD$(vDateMin) + RowNo() - 1 AS DateNumber,Date($(vDateMin) + RowNo() - 1) AS TempDateAUTOGENERATE 1WHILE $(vDateMin)+IterNo()-1<= $(vDateMax);

MasterCalendar:LOADTempDate as KEY_date,Day(TempDate) AS Day,Month(TempDate) AS Month,Year(TempDate) AS Year,Today() as DayNowRESIDENT TempCalendar ORDER BY TempDate ASC;
DROP TABLE TempCalendar;
LET vDateMin = Num(MakeDate(2010,1,1));LET vDateMax = Num(MakeDate(2015,1,1));//Floor(YearEnd(AddMonths(Today(), 12)));LET vDateToday = Num(Today());
//---------------------------------------------------------------------------------------------////STRUCTURATION//QUALIFY*;                                                                                           // Tous les champs sont préfixés par le nom de la table //UNQUALIFY "KEY_*";                                                                           // Tous les champs qui commencent par KEY_xxxx ne seront pas préfixés par le nom de la table ////---------------------------------------------------------------------------------------------//
CLIENT :LOAD [N° client] AS KEY_client,
    
ZoneFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is client$);

PRODUIT :LOAD REF as KEY_REF,
    
GROUPEFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is produit$);

AVOIR :LOAD ,
    
[N° client],
    
REF,
    
QTE,
    
DATEFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is Avoir$);

FACTURE :LOAD ,
    
[N° client],
    
REF,
    
QTE,
    
DATE FROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is Facture$);
//---------------------------------------------------------------------------------------------//
tmp_Link_Table:
NoConcatenateLOAD DISTINCT
       
,
    
[N° client],
    
REF,
    
QTE,
    
DATE RESIDENT FACTURE ;

// ELimination des doublons propres à AVOIRConcatenate( tmp_Link_Table )LOAD DISTINCT
        
,
    
[N° client],
    
REF,
    
QTE,
    
DATERESIDENT AVOIR ;
// Elimination des doublons dus aux combinaisons
// présentes dans les deux tables de faitLink_Table :NoConcatenateLOAD DISTINCT
     *RESIDENT tmp_Link_Table ;
DROP TABLE tmp_Link_Table ;

  FOR EACH table IN 'FACTURE' , 'AVOIR' , 'Link_Table'

 
    
LEFT JOIN( $(table)
    
LOAD

              
// champs_de_jointure               [N° client] ,
              
DATE ,
              
REF

              
//clé additionnelle               [N° client] & '|&|' & DATE & '|&|' & REF as clé
     RESIDENT
$(table) ;


    
// On ne garde les champs problématiques que dans la Link_Table     IF '$(table)' <> 'Link_Table' THEN

         
DROP FIELDS [N° client] , DATE , REF FROM $(table) ;

    
ENDIF
   NEXT table ;
//---------------------------------------------------------------------------------------------//

MERCI D'AVANCE POUR VOTRE AIDRE PRECIEUSE

Mathieu

rlp
Creator
Creator

Il vous faut supprimmer la ligne "N° ," qui pose problème. En effet, ce champ n'existe pas et il vous faut utiliser

[N° client] comme indiqué dans le code fourni.

Not applicable
Author

Aie, j'ai toujours un message d'erreur au chargement

Champ introuvable - <N° client>
tmp_Link_Table:

NoConcatenate
LOAD DISTINCT
     [N° client],
     REF,
     DATE 

RESIDENT FACTURE

rlp
Creator
Creator

Il vous faut enlever le QUALIFY * et le UNQUALIFY "KEY_*" puisque avec la méthode Link_Table, vous n'aurez plus de boucles.

De même, n renommer pas les champs :

REF en KEY_REF

et

[N° client] en KEY_client

Cela donne le code suivant:

// Idem Original


//---------------------------------------------------------------------------------------------//LET vDateMin = Num(MakeDate(2010,1,1));LET vDateMax = Num(MakeDate(2015,1,1));//Floor(YearEnd(AddMonths(Today(), 12)));LET vDateToday = Num(Today());

TempCalendar:LOAD$(vDateMin) + RowNo() - 1 AS DateNumber,Date($(vDateMin) + RowNo() - 1) AS TempDateAUTOGENERATE 1WHILE $(vDateMin)+IterNo()-1<= $(vDateMax);

MasterCalendar:LOADTempDate as KEY_date,Day(TempDate) AS Day,Month(TempDate) AS Month,Year(TempDate) AS Year,Today() as DayNowRESIDENT TempCalendar ORDER BY TempDate ASC;
DROP TABLE TempCalendar;
LET vDateMin = Num(MakeDate(2010,1,1));LET vDateMax = Num(MakeDate(2015,1,1));//Floor(YearEnd(AddMonths(Today(), 12)));LET vDateToday = Num(Today());

// Suppression des QUALIFY et UNQUALIFY

// Chargement initial sans renommage

CLIENT :LOAD [N° client] , // AS KEY_client,
    
ZoneFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is client$);

PRODUIT :LOAD REF , // , as KEY_REF,
    
GROUPEFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is produit$);

AVOIR :LOAD

     //,
    
[N° client],
    
REF,
    
QTE,
    
DATEFROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is Avoir$);

FACTURE :LOAD

     // ,
    
[N° client],
    
REF,
    
QTE,
    
DATE FROM
C:\Users\xxxxxxxxx\Desktop\BdD.xls
(
biff, embedded labels, table is Facture$);

/ /Création de la Link_Table => Code du premier post

// Elimination des doublons propres à FACTURE

tmp_Link_Table:

NoConcatenate

LOAD DISTINCT

     [N° client] ,

     date ,

     ref

RESIDENT FACTURE ;

// ELimination des doublons propres à AVOIR

Concatenate( tmp_Link_Table )

LOAD DISTINCT

     [N° client] ,

     date ,

     ref

RESIDENT AVOIR ;

// Elimination des doublons dus aux combinaisons

// présentes dans les deux tables de fait

Link_Table :

NoConcatenate

LOAD DISTINCT

     *

RESIDENT tmp_Link_Table ;

DROP TABLE tmp_Link_Table ;

FOR EACH table IN 'FACTURE' , 'AVOIR' , 'Link_Table'

     LEFT JOIN( $(table)

     LOAD

               // champs_de_jointure

              [N° client] ,

               date ,

               ref

               //clé additionnelle

               [N° client] & '|&|' & date & '|&|' & ref as clé

     RESIDENT $(table) ;

     // On ne garde les champs problématiques que dans la Link_Table

     IF '$(table)' <> 'Link_Table' THEN

          DROP FIELDS [N° client] , date , ref FROM $(table) ;

     ENDIF

NEXT table ;


Ce message a été modifié par: Richard Pressanti: Oubli d'une virgule

Not applicable
Author

On avance :

Les 3 dimensions sont bien liées avec la link_table. Dans la link_table j'ai bien les 3 champs problématiques

Le problème maintenant : la link_table n'a pas de jointure avec les 2 tables de fait

Lors du chargement des données, j'ai les 3 messages d'erreurs suivant :

Erreur de ligne de script :

LEFT JOIN( FACTURE

     LOAD

             

              [N° client] ,

               DATE ,

               REF

               

               [N° client] & '|&|' & DATE & '|&|' & REF as clé

     RESIDENT FACTURE

************************************************************************************

Erreur de ligne de script :

LEFT JOIN( AVOIR

     LOAD

             

              [N° client] ,

               DATE ,

               REF

               

               [N° client] & '|&|' & DATE & '|&|' & REF as clé

     RESIDENT AVOIR

************************************************************************************

Erreur de ligne de script :

LEFT JOIN( Link_Table

     LOAD

             

              [N° client] ,

               DATE ,

               REF

               

               [N° client] & '|&|' & DATE & '|&|' & REF as clé

     RESIDENT Link_Table

************************************************************************************

Au niveau du script, il semble que Qlikview n'aime pas tellement le code suivant :

//clé additionnelle
[N° client] & '|&|' & DATE & '|&|' & REF as clé
RESIDENT
$(table)

Merci pour votre aide

Mathieu

rlp
Creator
Creator

Mea culpa ! J'ai oublié une parenthèse:

Il faut écrire :

LEFT JOIN( $(table) )

Not applicable
Author

Oui en effet.. J'aurais pu le voir

Il manquait la petite virgule après REF .... et du coup, les données se chargent bien.

Ci dessous le résultat :

export.png

C'est parfait ! Merci beaucoup de voir aide

Not applicable
Author

Je viens de dupliquer le code dans mon environnement de production

Je m'aperçois d'un problème. Le chargement des données est ok. Le problème apparait dans le résultat des données exploitées.

J'exploite les données via un tableau dans QV avec comme dimensions : ANNEE et MOIS et comme expressions : sum (Montant_Facture)

Pour certains mois, le résultat n'est pas juste car :

Pour une même date et pour les mêmes ref un même client peut passer 2 commandes

Par ex :

- CDE 1 - date : 16/04/2013 - REF A : 1 200 / REF B : 1 800 / REF C : 1 152

- CDE 2 - date : 16/04/2013 - REF A : 1 200 / REF B : 1 800 / REF C : 1 152 / REF D : 1 152 / REF C : 648 / REF ......

Du coup, le montant Facture de la cde1 est pris en compte une fois ET une deuxième fois avec le montant Facture de la cde2

Faut 'il agir dans le script via la clé ?

Ou faut'il agir dans mon expression en mettant quelque chose comme DISTINCT ?

Merci d'avance