Bonjour à tous,

Je vais essayer de schématiser ce que je souhaite faire :
- j'ai un volume global G
- j'ai N produit avec pour chaque produit un volume V
- j'ai une table scenarios qui, pour chaque produit N me donne 1000 value (scenario0 à scenario999)
- je dois faire le calcul suivant pour chaque scenario, puis classer les résultats par ordre inverse et sélectionner les 10 premiers :

resultat0 = ( (N1 x V1) + (N2 x V2) + [...] ) / G

Bien entendu, le nombre de produits est variable, il peut y en avoir 2 comme dans mon exemple, 65, 123, 18, etc.

Donc mon idée était de faire une procédure stockée + une fonction qui feraient les choses suivantes :

- la fonction fait le calcul value x volume pour un produit_id et un scenario :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
 
CREATE FUNCTION `perf`(
	prod_id INTEGER UNSIGNED,
	vol INTEGER UNSIGNED,
	scen INTEGER UNSIGNED
) RETURNS double
BEGIN
	DECLARE result DOUBLE;
	SET result = (SELECT value * vol
		FROM product_scenarios
		WHERE product_id=prod_id AND scenario=scen);
RETURN result;
END
- la procédure stockée crée une table temporaire, fait une boucle de 0 à 999 en appelant à chaque fois la fonction pour un produit, un volume et un scénario, stocke le résultat dans la table temporaire, à la fin sélectionne les 10 premiers résultats order by desc, puis supprime la table temporaire.

La difficulté que j'ai c'est de pouvoir passer les couples produit_id/volume de manière dynamique...

Pour le moment, j'ai trouvé une astuce qui fonctionne pas trop mal mais qui m'oblige à faire la boucle de 0 à 1000 en PHP et de faire donc 1000 call de ma procédure... Si j'ai un petit nombre de produit, c'est rapide, mais dès que j'ai 50/60 produits, ça prend quelques secondes.

Voilà ce que je fais actuellement dans la procédure; "perfs" étant la table temporaire et "req" contenant en fait la concaténation des appels à ma fonction et de la division par G "perf(18,100000,0) + perf(234,2500000,0) + perf()... / G" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
CREATE PROCEDURE `store_perf`(
	req TEXT
)
BEGIN
        DECLARE sqlCMD TEXT;
        SET @sqlCMD = CONCAT('INSERT INTO perfs (theperf) SELECT ',req,' FROM product_scenarios LIMIT 1');
        PREPARE stmt FROM @sqlCMD;
	EXECUTE stmt;
	DEALLOCATE PREPARE stmt;
END
Y aurait-il une manière de passer à ma procédure l'ensemble des couples (N,V) et lui laisser faire la boucle de 0 à 999 en stockant au fur et à mesure les résultats renvoyés par la fonction ?

Si je ne suis pas assez clair, n'hésitez pas