Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Bonjour,
Dans le cadre de la construction d'une application, j'ai besoin de procéder à un mapping de valeurs "conditionné" à la somme des valeurs générées par les mappings appliqués sur lignes précédentes d'une table.
En détail pour le contexte, nous avons un premier logiciel de saisie des temps alimenté par nos collaborateurs dont la structure de l'export est ainsi faites :
Date_Ori | User_Ori | Customer_Ori | Contract_Ori | Item_Ori | Quantity_Ori | Label_Ori |
02/11/2020 | MTE | 03640 | 99 | P80 | 0.5 | Exemple libellé |
02/11/2020 | LBH | 02880 | 01 | P01 | 2 | Saisie temps |
02/11/2020 | MTE | 02880 | 01 | P01A | 2 | Saisie temps |
02/11/2020 | HAF | 00797 | 01 | P01 | 2 | Saisie temps |
Chaque mois, cette donnée est exporté dans un CRM qui en reprends la structure exacte, mais avec les spécificités suivantes :
La table finale après import dans le CRM et correction peut ainsi devenir :
Date_Crm | User_Crm | Customer_Crm | Contract_Crm | Item_Crm | Quantity_Crm | Label_Crm |
02/11/2020 | OC1 | 03640 | 99 | P80 | 0.5 | Exemple libellé |
02/11/2020 | OC1 | 02880 | 01 | P01 | 2 | Saisie temps |
02/11/2020 | OC1 | 02880 | 01 | P01 | 2 | Saisie temps |
02/11/2020 | OC1 | 02880 | 01 | P01 | 2 | Saisie temps |
Pour mon application Qlik Sense, j'ai besoin d'extraire ces temps et la seule donnée fiable (car corrigée) est celle provenant du CRM. Cependant cette dernière n'ayant pas le détail des utilisateurs propriétaire des lignes, j'ai besoin de faire un croisement avec les données d'origine pour en retrouver le détenteur initial.
Pour ce croisement, j'applique plusieurs mapping successif sur la base d'une concaténation de champs faisant office de clef d'identification en débutant par une recherche d'une égalité exacte entre ces clefs, puis à défaut de concordance trouvée, en appliquant plusieurs mapping tronqués d'un ou de plusieurs champs :
MappingIdentique:
MAPPING LOAD
Date_Ori & '|' & Customer_Ori & '|' & Contract_Ori & '|' Item_Ori & '|' & Quantity_Ori & '|' & Label_Ori AS KEY,
User_Ori
RESIDENT OriginalDatabase;
MappingWithoutContract:
MAPPING LOAD
Date_Ori & '|' & Customer_Ori & '|' Item_Ori & '|' & Quantity_Ori & '|' & Label_Ori AS KEY,
User_Ori
RESIDENT OriginalDatabase;
[...]
et ainsi de suite sur plusieurs combinaisons possibles par taux de certitudes (je vous passe le détail, j'ai environ 20 tables de mapping successifs pour évaluer toutes les combinaisons de corrections envisageables). Puis lors du chargement de la table extraite du CRM, l'application de ce mapping est ainsi fait :
Crm:
LOAD
Date_Crm,
APPLYMAP('MappingIdentique', Date_Crm & '|' & Customer_Crm & '|' & Contract_Crm & '|' Item_Crm & '|' & Quantity_Crm & '|' & Label_Crm, APPLYMAP('MappingWithoutContract', Date_Crm & '|' & Customer_Crm & '|' Item_Crm & '|' & Quantity_Crm & '|' & Label_Crm, [... 20 mapping successifs appliqués par taux décroissant de certitude ... ], 'Error Mapping') AS User_Crm,
Customer_Crm,
Contract_Crm,
Contract_Crm,
Item_Crm,
Quantity_Crm,
Label_Crm
RESIDENT CrmDatabase;
En soit, cette méthodologie même si imparfaites en terme de fiabilité reste relativement fonctionnelle dans la majorité des cas. Cependant, je me retrouve avec un problème d'application de ce mapping dans le cas ou ma clef n'est pas unique, ce qui arrive spécifiquement dans le cas de figure où mes collaborateurs saisissent exactement la même ligne d'activité (même date / code client / code contrat / code item / quantité & libellé). Dans le cas de figure ci dessus, un tel mapping au final donnerait le résultat suivant :
Date_Crm | User_Crm | Customer_Crm | Contract_Crm | Item_Crm | Quantity_Crm | Label_Crm |
02/11/2020 | MTE | 03640 | 99 | P80 | 0.5 | Exemple libellé |
02/11/2020 | LBH | 02880 | 01 | P01 | 2 | Saisie temps |
02/11/2020 | LBH | 02880 | 01 | P01 | 2 | Saisie temps |
02/11/2020 | LBH | 02880 | 01 | P01 | 2 | Saisie temps |
Mes trois dernières lignes étant identiques après concaténation des champs, et le mapping s'appliquant sur la première occurrence trouvée, je me retrouve à attribuer un propriétaire de ligne erroné.
Mon idée initialement était de construire une table intermédiaire qui soit la somme des temps par utilisateurs et par jours, et de "tester" cette table à la volée de l'application des mapping.
Si le collaborateur par les application de valeurs sur les lignes précédentes voit son quota d'heure du jour atteins, ce n'est plus lui que je veux charger mais le collaborateur d'après (soit la nième occurrence du Applymap()), et ainsi de suite.
Dans mon cas de figure, arrivée au chargement de ma troisième ligne, mon utilisateur LBH s'étant déjà vu attribuer son quota d'heure, ce ne peut plus être lui qui soit le détenteur des lignes à venir.
Cela étant dit, entre mon idée et sa matérialisation, il y a un léger gap 😂
La seule alternative qui me vienne en tête passe par des boucles, des tables temporaires par utilisateurs et des RangeSum() (entre autres choses...) mais avec plusieurs millions de lignes à traiter, je sais que l'optimisation du temps de traitement ne sera pas au rendez vous...
Une âme charitable et expérimentée aurait elle un début de piste / alternative / idée lumineuse à me proposer ?
Au besoin je peux construire un export simplifié (et nettoyé) de mon cas de figure pour mieux illustrer mon propos (car je doutes que mon pavé ci dessus soit si compréhensible 😋).
D'avance merci.
Bonjour
Tu as posé ta question dans le forum en anglais ..pas sur que tu aies beaucoup de réponse. J'ai lu ta longue demande et en effet c'est complexe pour "retrouver tes petits".
Toutefois si la base CRM est dans le même ordre de chargement que ta base d'origine , j'essaierai d'ajouter un champ "numéro de ligne" dans la base d'origine et dans la base CRM au chargement avec Rowno() ou Recno() ainsi tu aurais un ID unique et fiable entre tes deux bases et tu pourrais t'en servir comme clé pour un applymap ?
Mais c'est peut être bien plus compliqué que cela....
Bonjour et merci beaucoup pour ton temps et ton retour,
C'est une piste que j'ai exploré et qui aurait pu être fonctionnelle, mais malheureusement ce jeu d'import / exports entre les deux outils génère parfois des blocages temporaires de lignes (le temps qu'une correction soit apportée) et donc un décalage de ligne. Les X premières lignes jusqu'au premier blocage sont dans un ordre identique, mais dès le premier blocage rencontré (et pour tous les suivants), ces lignes une fois corrigées sont positionnées en dernière place. Cela peut représenter 1% de retraitement sur des batch de 50 000 lignes mensuelles, ce qui est entraine assez rapidement un décalage difficile à détricoter...
En fait dans cette approche comme dans mon optique initiale, ce qui m'aurait permis d'avancer serait l'utilisation d'une variable que je réactualiserais au chargement de chaque de ligne dans mon script, mais hormis le faire via une boucle Row by Row, je ne vois pas comment actualiser une variable au sein d'un même Load.