[VBA Access] Requête SQL

cs_observatoire Messages postés 75 Date d'inscription vendredi 10 mars 2006 Statut Membre Dernière intervention 23 août 2006 - 18 mai 2006 à 14:42
rvblog Messages postés 792 Date d'inscription vendredi 4 mars 2005 Statut Membre Dernière intervention 12 juin 2012 - 18 mai 2006 à 18:44
Bonjour,
Je souhaite réaliser des calculs sur des requêtes SQL. Dans un premier temps, pas de problème: je récolte les variables qui m'intéressent, à partir de différentes tables, avec des jointures, et je fais un calcul sur les colonnes.
Déjà c'est un peu lourd parce que pour tous les calculs intermédiaires, je réalise une requête création de table qui me donne systématiquement des messages d'avertissement.
Je veux ensuite faire la somme pour ma colonne calculée (ce pour deux tables différentes) et je souhaite diviser la première somme par la seconde. Et là je n'ai pas de variable de jointure.
Globalement ça marche, mais j'aimerais faire ça plus simplement, sans passer forcément par des tables ou des requêtes.
Autrement, est-il possible d'appeler la valeur de tel champ de telle table, la valeur de tel champ d'une autre table, de réaliser un calcul entre ces deux valeurs, et de les afficher quelque part?...
D'autre part, est-il possible de créer (par une requête SQL) une variable (plutôt constante) dont toutes les valeurs sont identiques: ça marche quand je demande dans SELECT une variable qui n'existait pas mais je ne sais pas où définir sa valeur, et quand je lance la requête un message me demande de rentrer la valeur.

Voici mon code :




Sub Requete()<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /?>








 








Dim MaBd As Database







Dim MaTab1… As QueryDef







Dim SqlBase1 As String








 








Set MaBd = CurrentDb








 








‘***************************************************************








 








SqlBase1 = "SELECT VAR4, Sum(Compte) AS CptBase1 " & _







"FROM Base1 " & _







"GROUP BY VAR1, VAR2, Var3, VAR4 " & _







"HAVING (((VAR1) = 'Choix1') AND ((VAR2)=Choix2) AND ((Var3)='Choix3'))"








 








Set MaTab1 = MaBd.CreateQueryDef("Qry1", SqlBase1)








 








‘***************************************************************








 








SqlBase2 = "SELECT VAR4, Sum(Compte) AS CptBase2 " & _







"FROM Base2 " & _







"GROUP BY VAR2, VAR5, VAR4 " & _







"HAVING (((VAR2)=Choix2) AND ((VAR5)='Choix5'))"








 








Set MaTab2 = MaBd.CreateQueryDef("Qry2", SqlBase2)








 








‘***************************************************************








 









SqlBase3 = "SELECT VAR4, Sum(Compte) AS CptBase3"

& _












"FROM Base3 " & _







"GROUP BY VAR4, VAR1, VAR6, VAR2 " & _







"HAVING (((VAR1)='Choix1') AND ((VAR6)='Choix6') AND ((VAR2)=Choix2))"








 








Set MaTab3 = MaBd.CreateQueryDef("Qry3", SqlBase3)








 








‘***************************************************************








 








SqlBase4= "SELECT Sum(Base4.Compte) AS CptBase4, cle " & _







"FROM Base4 " & _







"GROUP BY VAR3, VAR2, VAR1, VAR5 " & _







"HAVING (((VAR3)='Choix3') AND ((VAR2)=Choix2) AND ((VAR1)='Choix1') AND ((VAR5)='Choix5')) "








 








Set MaTab4 = MaBd.CreateQueryDef("Qry4", SqlBase4)








 








‘***************************************************************








 








Sql5 = "SELECT Qry3.VAR4, Qry3.CptBase3, Qry1.CptBase1, Qry2.CptBase2, Qry1.CptBase1/ Qry3.CptBase3* Qry2.CptBase2 AS taux " & _







"FROM (Qry3 LEFT JOIN Qry1 ON Qry3.VAR4 Qry1.VAR4) LEFT JOIN Qry2 ON Qry3.VAR4 Qry2.VAR4"








 








Set MaTab5 = MaBd.CreateQueryDef("Qry5", Sql5)








 








‘***************************************************************








 








SqlSum = "SELECT Sum(Qry5.taux) AS SommeDetaux, cle " & _







"FROM Qry5"








 








Set MaTab6 = MaBd.CreateQueryDef("TabSum", SqlSum)








 








‘***************************************************************








 








SqlTx = "SELECT TabSum.SommeDetaux/Qry4.CptBase4 AS Result " & _







"FROM TabSum INNER JOIN Qry4 ON TabSum.cle=Qry4.cle"








 








Set MaTab7 = MaBd.CreateQueryDef("TabTaux", SqlTx)








 








DoCmd.OpenQuery ("TabTaux")








 








End Sub









Merci

6 réponses

cs_observatoire Messages postés 75 Date d'inscription vendredi 10 mars 2006 Statut Membre Dernière intervention 23 août 2006
18 mai 2006 à 14:48
Voici la réponse de rvblog sur un message précédent:



Salut 716258 observatoire,

d'abord, n'oublies pas de mettre aussi, ici, un exemple du genre de celui que tu m'as envoyé en MP (

je n'ai pas la science infuse, et quelqu'un d'autre aura peut-être une meilleure réponse

). Je sais, pour avoir déjà discuté avec toi, que tu affines tes réponses au fur et à mesure, mais sur le forum, plus cela va, moins on répond au question qui ne comporte pas d'exemple précis (

c'est le réglement qui le veut

).

Evidemment, tu me connais, avant de répondre à ta question, je vais répondre à autre chose (

je suis comme ça, je n'y peux rien

).
Dans "
Dim MaTab1, MaTab2, MaTab3, MaTab4, MaTab5, MaTab6, MaTab7 As QueryDef
", seule
MaTab7
est de type QueryDef, les autres sont toutes des Variant. Il faudrait :

Dim
MaTab1
As
QueryDef, MaTab2
As
QueryDef,


... pour n'avoir que des QueryDef

Maintenant, ta réponse :


'Dans cette concaténation, l'instruction INTO crée une table,
'si on n'écrit pas cette instruction ( c'est ce que je fais ),
'la requête concaténée donne un jeu de réponse si on l'exécute, et si
'on ne l'exécute pas tout de suite, elle donne la description d'une table
'(d'un ensemble, en algèbre relationnelle), et on pourra la réutiliser
'dans une autre description de table (c'est aussi ce que je fais).

<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /?>







'je te donne, en plus, un modèle d'écriture pour les grosses requêtes.
'j'en conviens, c'est plus long, mais plus lisible, et plus maintenable :
'sélection

SqlBase1 = "SELECT"
   
's'il y a un espace à mettre, alors toujours au début d'un tronc de chaine
    'si la chaine dépasse la largeur de l'écran, et qu'il est à la fin, on peut le rater


    SqlBase1 = SqlBase1 & " Base1.VAR4"

    'pareil pour les virgules, parenthèses...

    SqlBase1 = SqlBase1 & "
,
Sum(Base1.Compte) AS CptBase1"

'source

SqlBase1 = SqlBase1 & " FROM Base1"

'regroupement

SqlBase1 = SqlBase1 & " GROUP BY"
    SqlBase1 = SqlBase1 & " Base1.VAR4"
'    en écrivant comme ça, tu peux


    SqlBase1 = SqlBase1 & ", Base1.VAR1"
'        commenter chaque champ


    SqlBase1 = SqlBase1 & ", Base1.VAR2"
'          important pour celui qui lit


    SqlBase1 = SqlBase1 & ", Base1.Var3"

'filtre

SqlBase1 = SqlBase1 & " HAVING ("
' exception pour la parenthèse

    SqlBase1 SqlBase1 & " ((Base1.VAR1) 'Choix1')"
    SqlBase1 = SqlBase1 & " AND"
    SqlBase1 = SqlBase1 & " ((Base1.VAR2)=Choix2)"
    SqlBase1 = SqlBase1 & " AND"
    SqlBase1 = SqlBase1 & " ((Base1.Var3)='Choix3')"
SqlBase1 = SqlBase1 & ")"





'sélection

Sql5 = "SELECT "
    Sql5 = Sql5 & " Base3.VAR4          As Base3_VAR4"
    Sql5 = Sql5 & ", Base3.CptBase3   As Base3_Compte"
    Sql5 = Sql5 & ", Base1.CptBase1   As Base1_Compte"
    Sql5 = Sql5 & ", Base2.CptBase2   As Base2_Compte"
   
'soit


    Sql5 = Sql5 & ", Base1.CptBase1/ Base3.CptBase3* Base2.CptBase2 AS taux"
   
'soit (je ne sais plus si on a le droit d'utiliser déjà les alias ou pas)


    Sql5 = Sql5 & ", Base1_Compte/ Base3_Compte * Base2_Compte AS taux"

'source

Sql5 = Sql5 & " FROM"
' les 3 tables virtuelles (juste décrites, pas exécutées)

    Sql5 = Sql5 & " (" &
SqlBase1
& ")"
    Sql5 = Sql5 & ", (" &
SqlBase3
& ")"
' que je n'ai pas définie, mais tu sauras le faire

    Sql5 = Sql5 & ", (" &
SqlBase2
& ")"
' que je n'ai pas définie, mais tu sauras le faire
'jointures

Sql5 = Sql5 & " WHERE"  
' idem, ici, pour les alias (à tester, c'est plus lisible les alias)

    Sql5 Sql5 & " Base3.VAR4 Base1.VAR4"    Sql5 Sql5 & " Base3.VAR4 Base2.VAR4"

Voilà, c'est un exemple à transposer. Je ne peux pas te promettre qu'une fois que tu auras traité tout ton code comme cela, tu obtiendras des performances hors du commun, mais c'est une alternative qu'il faut tester, voire même, disséminer avec parcimonie (

créer certaines tables temporaires et pas certaines autres

).

Et pour la constante, comme je t'ai dit en MP :

SELECT UnVraiChamp As
Champ1
, True As
Champ2


FROM
TRUC
renverra quelque chose du genre :

Champ1
        
Champ2


12,5                 True
156                  True
189                  True
Très pratique pour rendre des schémas de table SQL compatibles en vue d'une opération SQL nécessitant le même schéma dans toutes les tables.

voilà,
à+






rvb



logn







 
0
rvblog Messages postés 792 Date d'inscription vendredi 4 mars 2005 Statut Membre Dernière intervention 12 juin 2012 7
18 mai 2006 à 15:18
Salut 716258 observatoire,


c'est vrai, sans les couleurs, c'est tout de suite moins lisible :)

à+
PS : pour les autres qui cherchent à comprendre, ceci vient d'un post un peu plus ancien, qui a été supprimé, mais dont =716258 observatoire avait pensé à faire quelques sauvegarde.

Le problème reste entier.
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
0
cs_observatoire Messages postés 75 Date d'inscription vendredi 10 mars 2006 Statut Membre Dernière intervention 23 août 2006
18 mai 2006 à 15:20
Le problème avec ce code c'est me donne le message d'erreur:
'Impossible de spécifier plusieurs fois le nom de la table [mailto:'%$##@_Alias' '%$##@_Alias'] dans la clause FROM'
qui arrive au moment d'ouvrir la dernière requête "TabTaux".


Il semblerait que le fait d'insérer des codes SQL dans d'autres codes SQL, gêne quelque peu le programme: cela génère certainement des répétitions...
0
rvblog Messages postés 792 Date d'inscription vendredi 4 mars 2005 Statut Membre Dernière intervention 12 juin 2012 7
18 mai 2006 à 15:29
Bon, d'abord, la technique des requêtes imbriquées (ou sous-requête) fonctionne depuis la nuit des temps, elle fait partie de la norme (d'ailleurs, observes l'écriture de tes 2 LEFT JOIN originels). C'est même LA norme. C'est le S de SQL (Structured Query Language).

Donc, aucun doute sur la faisabilité.

Par contre, évidemment, modifies les Alias pour leur faire porter des noms uniques, mais compréhensibles quand même (le repère, c'est, si tu es obligée d'aller voir la description de la sous-requête pour comprendre ce qu'est l'ALIAS, c'est que son nom est mal choisi).

courage, à +

rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_observatoire Messages postés 75 Date d'inscription vendredi 10 mars 2006 Statut Membre Dernière intervention 23 août 2006
18 mai 2006 à 16:00
Très bien, et loin de moi l'idée de remettre en cause tout ton savoir. Seulement je comprend qu'il faille mettre des alias pour les tables, mais comment et où les affecter? même dans la doc Access c'est pas dit! Après le nom de la table de la clause FROM?
0
rvblog Messages postés 792 Date d'inscription vendredi 4 mars 2005 Statut Membre Dernière intervention 12 juin 2012 7
18 mai 2006 à 18:44
Scuse,
j'ai pas vu le message.

tu peux mettre un Alias sur un table comme ceci :

SELECT Truc
 FROM
(
   SELECT Machin As Truc1 
   FROM MaTable1 As TaTable1
)
,
(
   SELECT Machin As Truc1 
   FROM MaTable2 As TaTable2
)
 WHERE
   TaTable1.ID = TaTable2.ID

En fait, tu peux mettre des Alias un peu partout, mais pas dans n'importe quel sens (d'ailleurs, j'ai un doute quand à celui-ci, mais je te laisse tester, j'ai pas le temps).

à+

rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
0
Rejoignez-nous