Bonjour,
Dans une de mes requêtes, je souhaiterais calculer le produit de plusieurs valeurs à partir d'un regroupement (de la même façon qu'Access calcule la moyenne), y a t'il une expression pour ça?
Merci d'avance
Marie
[débutante Access]
Version imprimable
Bonjour,
Dans une de mes requêtes, je souhaiterais calculer le produit de plusieurs valeurs à partir d'un regroupement (de la même façon qu'Access calcule la moyenne), y a t'il une expression pour ça?
Merci d'avance
Marie
[débutante Access]
Bonjour,
Tu crées une deuxième requête et tu fais la multiplication des valeurs regroupées
Mais mon problème c'est bien ça, comment faire la multiplication??
En fait j'ai 2 colonnes, A et B.
Je veux regrouper à partir de A pour obtenir en valeur sur B le produit des valeurs regroupées (de B bien sûr). Et je ne connais pas l'écriture de l'instruction (je suis vraiment débutante sur les requêtes)
bonjour,
on peut s'en sortir avec une astuce mathématique sur le log népérien ( ln(a)+ln(b) = ln(ab) )
Code:
1
2
3
4
5 SELECT LaTable.A, exp(sum(log(LaTable.B))) as Multipli FROM LaTable GROUP BY LaTable.A;
mais attention aux dépassements de capacité.
D'accord.
Mais ça je l'écriscomment dans ma requête?..... (vraiment débutante...)
Parce que sortie de l'affichage avec les tables, j'ai un peu de mal...
Il faut basculer en "mode SQL" et dans la fenêtre vierge tu colles le code en adaptant les noms de tables&champs. Tu peux ensuite re-basculer en "mode création" pour voir comment Access l’interprète.
Note que la fonction Log (logarithme népérien) est définie pour des valeurs de B appartenant à ]0,+∞[ (un peu de révisions pour les presque-futurs bacheliers qui vont débuter l’épreuve de Maths cette semaine:mrgreen:).
Bonjour,
Alors là je me retrouve avec un message "Appel de procédure incorrect" quand j'essaye de repasser en mode création.
En fait, je me suis basée sur la formule automatique créée avec un regroupement en Compte, et j'ai modifié le compte avec "exp(sum(log"
bonjour,
sans doute que tu as des valeurs de B en dehors du domaine de définition de la fonction Logn.Citation:
je me retrouve avec un message "Appel de procédure incorrect"...
J'avais prévenu:D
il va falloir créer ta propre fonction en VBA, du style:Citation:
Envoyé par f-leb
fonction (rédigée très rapidement donc à tester) à copier/coller dans un module et à adapter selon tes noms de champs&tables.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 Public Function multipli(champA As Variant) As Double Dim db As Database Dim rst As DAO.Recordset Dim strSQL As String Dim resultat As Double On Error GoTo err Set db = CurrentDb strSQL = "SELECT LaTable.B FROM LaTable WHERE LaTable.A='" & champA & "';" resultat = 1# ' si champA est numérique, il faut alors écrire: ' "SELECT LaTable.B FROM LaTable WHERE LaTable.A=" & champA Set rst = db.OpenRecordset(strSQL) If rst.EOF Then 'la requête ne renvoit aucun enregistrement Exit Function Else rst.MoveFirst While Not rst.EOF resultat = resultat * rst.Fields(0) 'calcul rst.MoveNext Wend End If multipli = resultat rst.Close Set rst = Nothing err: End Function
Puis dans une nouvelle requête:
Code:
1
2
3 SELECT LaTable.A, multipli(LaTable.A) AS Multiplication FROM LaTable GROUP BY LaTable.A;
Bonjour,
Alors, j'ai lancé tout ça, ça fonctionne sans message d'erreur, mais le résultat n'est pas encore bon.
Mes valeurs dans B sont comprises entre 0 et 1, avec 1 à 2 décimales (je ne sais pas si ça peut interférer...), et pour le moment ma colonne Multiplication ne donne que 0.00 (dans les propriétés, j'ai attribué un format Standard à 2 décimales).
Par ailleurs, petit détail qui joue peut-être, A et B ne sont pas situés dans la même table (mais j'ajoute bien à chaque fois les INNER JOIN)
Le temps d'exécution de la requêtes est toujours assez long.
Bonjour,
0.1x0.1x0.1=0.001, avec deux décimales ça fait 0.00 ! Avec des nombres entres 0 et 1, la multiplication peut tendre rapidement vers 0, il faudrait au moins essayer avec plus de décimales ou avec un format nombre général…Citation:
Envoyé par marie.l
Eventuellement, poste le code SQL si le problème persiste.Citation:
Envoyé par marie.l
Assez long comment ? 5 secondes ? 10 minutes ?Citation:
Envoyé par marie.l
Donne-nous une idée de la volumétrie de tes données (nombres de lignes de chacune des deux tables en gros). Pour une valeur de A, combien de termes B à multiplier entre eux (en moyenne) ?
Bon, autant pour moi, les maths sont loin. Mais le nombre de décimales ne change rien, je me retrouve quand même avec des 0 partout (nombre général, 7 décimales).
A contient 600 lignes, B 2000. En moyenne, il y a 2 B pour 1 A, mais ça peut monter jusqu'à 10 B. Et c'est long, c'est à dire que ça dure 30 secondes (oui bon, c'est pas si long que ça d'accord...)
Alors pour mon code, le SQL de la requête donne ça :
Et la fonction :Code:
1
2
3 SELECT Risque_Correction_Poste.NumPosteSiteRisque, multipli(Risque_Correction_Poste.NumPosteSiteRisque) AS Multiplication, Count(Corr_Type.Valeur) AS CompteDeValeur FROM ((Corr_Type INNER JOIN Correction ON Corr_Type.TypeCorr = Correction.TypeCorr) INNER JOIN Risque_Correction ON Correction.NumCorr = Risque_Correction.NumCorr) INNER JOIN Risque_Correction_Poste ON Risque_Correction.NumRisqueCorr = Risque_Correction_Poste.NumRisqueCorr GROUP BY Risque_Correction_Poste.NumPosteSiteRisque;
... ça fait une bonne longueur.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 Public Function multipli(NumPosteSiteRisque As Variant) As Double Dim db As Database Dim rst As DAO.Recordset Dim strSQL As String Dim resultat As Double On Error GoTo err Set db = CurrentDb strSQL = "SELECT Corr_Type.Valeur FROM Corr_Type INNER JOIN Correction ON Corr_Type.TypeCorr = Correction.TypeCorr)INNER JOIN Risque_Correction ON Correction.NumCorr = Risque_Correction.NumCorr)INNER JOIN Risque_Correction_Poste ON Risque_Correction.NumRisqueCorr = Risque_Correction_Poste.NumRisqueCorr WHERE Risque_Correction_Poste.NumPosteSiteRisque='" & NumPosteSiteRisque resultat = 1# ' si champA est numérique, il faut alors écrire: ' "SELECT LaTable.B FROM LaTable WHERE LaTable.A=" & champA Set rst = db.OpenRecordset(strSQL) If rst.EOF Then 'la requête ne renvoit aucun enregistrement Exit Function Else rst.MoveFirst While Not rst.EOF resultat = resultat * rst.Fields(0) 'calcul rst.MoveNext Wend End If multipli = resultat rst.Close Set rst = Nothing err: End Function
bonjour,
Essaye en enlevant l'apostrophe en rouge...Code:strSQL = "SELECT Corr_Type.Valeur FROM Corr_Type ... WHERE Risque_Correction_Poste.NumPosteSiteRisque='" & NumPosteSiteRisque
Si non, insère un debug.print (strSQL) dans le code VBA pour voir si la chaîne strSQL a une bonne tête.
L'apostrophe ne change rien.
J'ai essayé d'insérer le Debug.Print mais soit je ne l'ai pas mis au bon endroit, soit ça n'a rien changé.
Il y a quand même un truc qui me chifonne dans cette histoire. Si on reprend le code de la requête
pourquoi est-ce qu'on applique multipli à mon champ A et pas au B?? On lui a demandé de le faire dans ce sens dans le VBA?Code:
1
2
3 SELECT Risque_Correction_Poste.NumPosteSiteRisque, multipli(Risque_Correction_Poste.NumPosteSiteRisque) AS Multiplication FROM ((Corr_Type [...] ON Risque_Correction.NumRisqueCorr = Risque_Correction_Poste.NumRisqueCorr GROUP BY Risque_Correction_Poste.NumPosteSiteRisque;
** Champ A = Risque_Correction_Poste.NumPosteSiteRisque
** Champ B = Corr_Type.Valeur
Tilt !:idea::idea:
Supprime temporairement le On error goto, tu devrais avoir un message d’erreur.
Dans strSQL, je vois des parenthèses fermantes mais il manque les parenthèses ouvrantes.
On va y arriver, on va y arriver:mrgreen:
Yahoo!
On y est, c'est bien les parenthèses qui le perturbaient. En tout cas merci BEAUCOUP
ET heu... je ne ferme pas encore la discussion, les valeurs là doivent me servir pour calculer un autre champ alors si par hasard ça ne fonctionne pas là, je te redemanderai :mrgreen:.
... ce que je vais faire tout de suite finalement, ça m'évitera un petit casse tête je crois.
Donc je souhaiterais que le résultat de cette petite multiplication soit reporté dans une seconde requête où là mon champ A n'est pas (et ne doit pas être) regroupé, j'imagine (j'espère) que c'est simple, mais autant profiter de tes compétences!
Bonjour,
Avec ou sans GROUP BY, il suffit d’appeler la fonction avec le champ A comme paramètre dans le SELECT :Citation:
Envoyé par marie.l
Code:
1
2 SELECT LaTable.A, multipli(LaTable.A) AS Multiplication, AutreChamp FROM LaTable INNER JOIN AutreTable ON WHERE
La requête de la function Multipli se charge de récupérer les champs B correspondants :
Est-ce que le traitement prend toujours autant de temps ?Code:strSQL = "SELECT LaTable.B FROM LaTable WHERE LaTable.A=" & champA
Note que la fonction devrait peut-être prendre en compte des cas particuliers ou B=Null, B=0 …
Bonjour,
Alors, la simple transposition à ma requête a bien fonctionné, on avance bien!
Et maintenant si je veux que mon champ B soit issu d'une valeur stockée dans la requête, je lui dis comment?
Bon, si j'exagère tu me le dis hein... :?
Lol :roll:
Bon, j'essaye de faire ça brièvement. Ma BDD me permet de faire le document unique d'évaluation des risques professionnels de mon entreprise.
Le champ A est l'ID des différents risques relevés. Le champ B est la valeur attribuée aux différentes corrections possibles à mettre en place pour minimiser le risque, en fait c'est un coefficient réducteur de risque.
Mais les corrections peuvent soit être appliquées actuellement, soit être simplement préconisées.
Si les corrections sont appliquées, je veux que le coefficient réducteur soit appliqué tel quel.
Par contre, si les corrections sont préconisées, je ne veux pas réduire le risque.
J'ai donc créé un champ B' dans ma requête où les corrections préconisées ont toutes une valeur de 1 et où celles appliquées ont leur valeur réelle.
Et je voudrais donc que le produit soit réalisé sur la base de B' et pas de B.
Voilà, tu sais tout.
Ca va mieux comme ça?