Interpolation sur valeurs de retour - SQL/NoSQL - Programmation
Marsh Posté le 23-11-2011 à 15:38:41
Tu veux dire que, par ex, un processus P1 a comme valeurs 1, 2, 3, 4, 5 et qu'un autre processus P2 n'a que 1, 2, 4 et donc, faut compléter pour ce processus en rajoutant les valeurs 3 et 5?
Marsh Posté le 23-11-2011 à 16:07:11
En fait l'interpolation doit être fait sur le couple valeur-timestamp.
Donc ça serait plutôt :
P1 (valeur; timestamp): (1;2000), (2;2001), (3;2005), (4;2010)
P2 (valeur; timestamp): (20;1999), (40;2003)
Ce que je dois avoir c'est 2 "Hash" de même longueur (4), dont le premier élément se réfère au 1er timestamp (1999) et le dernier, au dernier (2010).
On doit donc interpoler linéairement et reconstruire les valeurs "qui vont bien".
Par la suite, il faudra que je puisse spécifier le nombre de valeurs du vecteur (ce qui me force le "timestep" ), le timestep de début et de fin.
Je suis condamné à tout sortir de la base et mouliner dessus en Java dans mon business ou bien il y a moins lourd?
Marsh Posté le 23-11-2011 à 16:19:55
Si j'ai bien compris, tu voudrais en sortie, pour chaque processus, une liste de timestamp qui va du plus faible au plus élevé dans la bd, et pour chaque timestamp, une valeur correspondante ou 0 dans le cas où y'a pas de timestamp pour un processus. Ca donnerait :
P1 : (0;1999), (1;2000), (2;2001), (0;2002), (0;2003), (0;2004), (3;2005), (0;2006), (0;2007), (0;2008), (0;2009), (4;2010)
P2 : (20;1999), (0;2000), (0;2001), (0;2002), (40;2003), (0;2004), (0;2005), (0;2006), (0;2007), (0;2008), (0;2009), (0;2010)
J'ai bon?
Si c'est ça, j'ai eu un pb similaire à gérer dans mon soft de help-desk Astres (cf ma signature) pour produire des stats en histogramme empilé. Je devais générer, sur une période et à une certaine fréquence, la liste des dates sur lesquelles consolider les stats.
Ex : lister les tickets de type T1 et T2 reçus par mois, sur 1 an entre le 01/01/2011 et le 31/12/2011.
Il fallait générer la liste des 12 mois et trouver le nb de tickets reçus pour chaque type.
Ce que je faisais en php, c'est d'abord de générer les mois compris entre mes 2 dates sous la forme "yyyy-mm", ces valeurs étant des clés dans un tableau associatif.
Code :
|
Ensuite, je faisais une requête SQL qui listait mes tickets d'un type donné et dans le select, je mettais le timestamp de réception de chaque ticket sous la forme "yyyy-mm". Ensuite, j'avais plus qu'à faire +1 dans ma variable $MaStat sur la bonne "clé"
Marsh Posté le 23-11-2011 à 16:26:24
Presque (désolé, j'ai un peu de mal aujourd'hui ).
P1 : (0;1999), (1;2000), (2;2001), (X;2002), (X;2003), (X;2004), (3;2005), (Y;2006), (Y;2007), (Y;2008), (Y;2009), (4;2010)
X doit être interpolé entre 2 et 3. Suivant la méthode d'interpolation (à voir laquelle on utilise. Pour le moment n'importe laquelle fera l'affaire), la valeur sera différente (2, 3 ou alors une progression linéaire entre 2 et 3). Idem pour Y
P2 subi ensuite le même traitement.
C'est plus clair maintenant?
Marsh Posté le 23-11-2011 à 16:33:56
Ah oui, d'accord. Là, c'est chaud ton truc Franchement, je doute que tu y arrive en SQL pure...
Marsh Posté le 23-11-2011 à 16:35:34
Au départ j'étais quasiment sûr que c'était impossible mais après avoir trouvé les fonctions d'analyse j'ai eu une lueur d'espoir ... Et je pense que si j'arrive à le faire dans la base ce sera certainement plus rapide que de mouliner dessus en Java
Marsh Posté le 23-11-2011 à 22:01:34
Salut
Faire en une seule requete je suis pas sur que ca soit faisable à première vue, mais d'un autre coté le problème en lui-meme n'a pas l'air bien compliqué.
C'est quoi que t'appelles "à grands coups de moulinette" dans ton premier post? Tu peux préciser ce qui va poser problème quand tu vas scaler? Une table avec des centaines de milliers de lignes c'est pas la mort a priori, si t'as les indexs comme il faut sur tes colonnes, obtenir tous les count() ne devrait pas poser de problèmes.
Si j'ai bien compris ton exemple, ta matrice avec p1/p2 avant extrapolation devrait ressembler à
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 |
Une fois que t'as ca, l'extrapolation c'est juste un simple algo non? Je pense qu'il me manque un truc pour bien cerner ton problème. Ou alors t'as des problèmes de performance avec les counts?
Marsh Posté le 23-11-2011 à 22:13:00
Salut,
Tu as absolument tout compris. Mes index et count sont en ordre, donc il ne devraient pas trop poser de problèmes de perf. Par contre :
- comment obtenir cette matrice de la manière plus performante ?
- si j'ai bien compris, l'interpolation sur les valeurs, je vais devoir la faire de toutes façons dans le layer metier, juste? Il n'y a rien dans oracle qui puisse le faire pour moi avec de bonnes perf?
Marsh Posté le 24-11-2011 à 06:18:57
Mh ok, bon je pense qu'il n'y a pas de fonction Oracle prédéfinie dans ton cas.
Pour la matrice avant interpolation, je pense pas que tu puisses échapper aux counts sauf si tu crées une table qui tient à jour chaque count pour les paires ID/valeur. Tu l'initialises avec les counts existants lors de sa création, puis tu la maintiens avec des triggers sur la table production_data (à chaque fois que tu insères/modifies/efface une ligne, pouf tu upates le count correspondant). Du coup au lieu de devoir faire les counts à chaque fois, tu peux directement accéder à la valeur dans ta table. Pas sur que ca gagne beaucoup sauf si t'as une quantité énorme de ID/valeurs possibles, ou ptetre aussi si tu passes ton temps à vouloir regénérer ta matrice.
Pour l'interpolation, je pense pas que t'y échappes, donc ouai layer métier. Ou tu peux faire ca en PL/SQL aussi (m'enfin bon on pourra toujours considérer ca comme métier, pis c'est surement moins chiant à coder en Java).
J'ai dans l'idée que ca serait meme probablement faisaible avec une poignée de requetes SQL qui généreraient une table "réplique" de la matrice, interpolation comprise, mais ca sent le truc fait à la truelle et ca m'étonnerait que ca soit plus performant que de le faire en Java. Mais bon maintenant que j'ai l'idée en tete, j'tenterai demain je pense, mais attends toi à du bon gras qui tache.
Marsh Posté le 24-11-2011 à 19:50:20
Volontiers
Marsh Posté le 25-11-2011 à 04:11:35
Ah merde j'avais commencé puis c'était encore plus horrible que prévu alors j'allais laisser tomber, mais si tu insistes...
Tiens, voilà du boudin!
Le fait que le nombre de valeurs soit dynamique empeche de tout faire en SQL simple et force le passage à PL/SQL (pour pouvoir utiliser execute_immediate et consorts).
En plus de ca j'ai tapé dans la limite de longueur de chaine de caractère générable par une concaténation de chaine donc y a fallu contourner, comme si c'était pas assez le bordel.
J'ai la flemme de commenter précisément tellement c'est tiré par les cheveux. Si tu comprends pas les requetes c'est normal! Le pire c'est que ca marche!!
Code :
|
PROCESS_ID V_1999 V_2000 V_2001 V_2002 V_2003 V_2004 V_2005 V_2006 V_2007 V_2008 V_2009 V_2010 |
Bon pour l'instant ca ne calcule pas si la borne inférieure ou supérieure n'est pas connue (ex pour 1999 pour P1 et au-delà de 2003 pour P2). Si tu veux y mettre des valeurs arbitraires (ex: 0 pour borne inf, plus haute valeur atteinte pour borne sup), ca te rajoute une étape. Si tu ne veux pas que le 0 influes sur l'extrapolation tu rajoutes ca dans la matrice extrapolée, sinon tu mets ca dans la matrice non extrapolée avant l'extrapolation.
Marsh Posté le 27-11-2011 à 07:13:55
oua.... c'est hallucinant
Je vais essayer de comprendre comment ca marche . par contre je me demande si c'est plus rapide que en java... à voir..
En tous cas merci pour ton effort !!
Marsh Posté le 28-11-2011 à 00:18:13
Pas de pb, j'ai appris un truc en le faisant donc c'est meme pas perdu pour moi!
Merde en relisant je m'apercois que j'ai laissé des variables qui servent à rien, ca va pas aider pour la compréhension.
Par contre non, ya aucune garantie que ca soit plus rapide qu'en Java.
Marsh Posté le 28-11-2011 à 08:54:26
Théoriquement une DB c'est fait pour sortir des données et c'est a l'appli de formater le tout.
En réalité il faut de temps en temps faire un mix pour gagner du temps mais dans ce cas ci ce serai mieux de "boucher les trous" dans l'appli, ce sera plus clair, plus flexible et plus facil a maintenir.
En fait le probleme c'est pas vraiment l'interpolation mais le nombre variable de colonne, c'est relativement compliqué de sortir le résultat tout cuit du sgbd alors que c'est facil de le sortir sous forme clé/valeur et de reformater le tout dans l'appli a l'affichage.
Marsh Posté le 23-11-2011 à 14:41:59
Bonjour,
Je travaille actuellement sur Oracle 11g voici le contexte de mon problème:
J'ai une table production_data qui contient plusieurs centaines de milliers de valeurs de production. Les valeurs ont :
- un id (PK, int)
- un process_id (FK, int)
- une valeur (int)
- un timestamp (Timestamp)
Le resultat de select count(*) from production_data group by process_id montre que la répartition en fonction du process_id n'est pas égale (ce qui est normal).
Le problème:
Au vu des opérations que je fais après dans ma couche métier, je dois sortir de la base une matrice ayant autant de colonne que de process_id, et autant de lignes que de valeurs. Vu que tous les process_id n'ont pas le même nombre de valeurs, il faut que j'interpole les autres (par interpolation linéaire par exemple).
Est-ce que vous voyez une manière simple (et surtout performante) de faire ça? En ce moment je le fais à grands coups de moulinette mais je doute que ce soit très efficace et j'ai peur du scale-up ... J'ai vu que je pourrais peut-être utiliser des fonctions comme percentile_cont(X), en moulinant sur X, mais là aussi je suis sceptique..
Merci d'avance!
---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait