Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Algoritme sur des calculs de trajet

17 réponses
Avatar
Kolele
Salut et bonne année à toutes et à tous !
Dans ACCESS 2002, je cherche à déterminer des trajets de profs visitant en
entreprise leurs étudiants stagiaires (pour ensuite calculer leurs frais de
déplacement). Lorsque le prof visite un seul élève par jour, no problemo car
le départ et l'arrivée sont des constantes : CommuneDépart = le lycée ;
CommuneArrivée = l'entreprise.
La difficulté provient de ce que chaque prof visite plusieurs stagiaires le
même jour : ils partent du lycée visiter le premier stagiaire, mais ensuite
repartent de l'entreprise visitée pour se rendre dans l'entreprise du
deuxième stagiaire. La commune de départ change.

Soit une requête sélection reprenant, pour chaque prof, deux champs :
DateVisiteProf (la date où le prof effectue la visite du stagiaire) et
CommuneEntreprise (la commune de l'entreprise où il doit se rendre). Je
voudrais, par un algorithme simple, renvoyer les valeurs de deux champs
calculés de ma requête : CommuneDépart et CommuneArrivée.

- Pour CommuneDépart :
SI il n'y a pas d'autre visite le même jour, ALORS CommuneDépart = "THIAIS"
(le lycée).
SINON, CommuneDépart = CommuneArrivée de l'enregistrement précédent (la
visite précédente).

- Pour CommuneArrivée :
SI il y a déjà eu un déplacement le même jour et que la visite est la
dernière du jour, ALORS, CommuneArrivée = "THIAIS" (retour au lycée).
SINON, CommuneArrivée = CommuneEntreprise

J'arrive à faire ça sur EXCEL, par des fonction en SI ET OU enchâssées.
Sur ACCESS, dans une requête, je n'arrive pas à désigner la valeur de
l'enregistrement précédent. Et le VBA n'est pas ma langue maternelle. Merci
du coup de m

--
Pierre.

7 réponses

1 2
Avatar
Kolele
Bonsoir à tous,
1)Michel, je te promets de regarder ton code, dès que j'en aurais fini avec
le précédent. Je débute en SQL, et il faut que j'y aille pas à pas
2) Toujours sur le même projet,
La requête union de db fonctionne comme sur des roulettes :

SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet],
IIf([OrdreTrajet]=1, "THIAIS",
DLookUp("[NomCommune]","[11-PlannificationVisiteSousForm]","[CléPersonnel]="
& [CléPersonnel] & " and [DateVisiteProf]=#" & [DateVisiteProf] & "# and
[OrdreTrajet]=" & [OrdreTrajet]
-1)) AS CommuneDépart, [NomCommune] FROM [11-PlannificationVisiteSousForm]

UNION SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet]+1,
[NomCommune], "THIAIS"
FROM [11-PlannificationVisiteSousForm]D1
WHERE [OrdreTrajet]=(select max([OrdreTrajet]) from
[11-PlannificationVisiteSousForm]D2 WHERE D2.[CléPersonnel]Ñ.[CléPersonnel]
and D2.[DateVisiteProf]Ñ.[DateVisiteProf]);


Je veux faire ensuite une requête à partir de la précédente, reprenant tous
les champs, plus un champ calculer avec une fonction qui RechDom, pour aller
chercher dans une table la distance entre les CommuneDépart et NomCommune :

SELECT RequêteUnion2.*,
DLookUp("[Distance]","[TrajetsPetiteCouronne1]","[CommuneDépart]=" &
[CommuneDépart] & " and [NomCommune]=" & [NomCommune]) AS Distancier
FROM RequêteUnion2;

Msg d'erreur partout sur le champ calculé : "erreur de syntaxe (opérateur
absent) dans l'expression "[CommuneDépart]=ORLY and [NomCommune]=VITRY SUR
SEINE"

Que faire ?
--
Pierre.
Avatar
db
Kolele a écrit :
Bonsoir à tous,
1)Michel, je te promets de regarder ton code, dès que j'en aurais fini avec
le précédent. Je débute en SQL, et il faut que j'y aille pas à pas
2) Toujours sur le même projet,
La requête union de db fonctionne comme sur des roulettes :

SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet],
IIf([OrdreTrajet]=1, "THIAIS",
DLookUp("[NomCommune]","[11-PlannificationVisiteSousForm]","[CléPersonnel]="
& [CléPersonnel] & " and [DateVisiteProf]=#" & [DateVisiteProf] & "# and
[OrdreTrajet]=" & [OrdreTrajet]
-1)) AS CommuneDépart, [NomCommune] FROM [11-PlannificationVisiteSousForm]

UNION SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet]+1,
[NomCommune], "THIAIS"
FROM [11-PlannificationVisiteSousForm]D1
WHERE [OrdreTrajet]=(select max([OrdreTrajet]) from
[11-PlannificationVisiteSousForm]D2 WHERE D2.[CléPersonnel]Ñ.[CléPersonnel]
and D2.[DateVisiteProf]Ñ.[DateVisiteProf]);


Je veux faire ensuite une requête à partir de la précédente, reprenant tous
les champs, plus un champ calculer avec une fonction qui RechDom, pour aller
chercher dans une table la distance entre les CommuneDépart et NomCommune :

SELECT RequêteUnion2.*,
DLookUp("[Distance]","[TrajetsPetiteCouronne1]","[CommuneDépart]=" &
[CommuneDépart] & " and [NomCommune]=" & [NomCommune]) AS Distancier
FROM RequêteUnion2;

Msg d'erreur partout sur le champ calculé : "erreur de syntaxe (opérateur
absent) dans l'expression "[CommuneDépart]=ORLY and [NomCommune]=VITRY SUR
SEINE"

Que faire ?



Faire en sorte que ORLY et VITRY SUR SEINE soient encadrés par des parenthèses (ou des apostrophes) :

SELECT RequêteUnion2.*,
DLookUp("[Distance]","[TrajetsPetiteCouronne1]","[CommuneDépart]='" &
[CommuneDépart] & "' and [NomCommune]='" & [NomCommune]) & "'" AS Distancier
FROM RequêteUnion2;

(à regarder avec une police type Courier, pour bien voir les apostrophes et les parenthèses)

Mais il serait beaucoup plus judicieux (et rapide !) d'inclure la table Distancier dans la requête et de mettre une double jointure à partir de CommuneDépart et de NomCommune (les champs s'appellent aussi comme ça dans la table Distancier ?) : il resterait juste à mettre le champ Distance dans la requête.

db
Avatar
Kolele
Db,

1) J'ai collé ton code mais ça ne fonctionne pas encore. J'ai remplacé les
apostrophes par des parenthèses, pour voir : toujours le même message
d'erreur.

"erreur de syntaxe dans la chaîne dans l'expression
"[CommuneDépart]='THIAIS' and [NomCommune]='ORLY'"

2) Pour faire un peu d'ordre, je viens de donner des noms différents aux
champs de la table[TrajetsPetiteCouronne1]contenant les distances, pour plus
de clarté :

CléTrajet (type numéroauto), VilleDépart (type texte), VilleArrivée (type
texte)
Distance (type numérique, réel double)

3) dans la requête UNION, je nomme le résultat de la fonction Dlookup :
[CommuneArrivée]. Ce n'est pas grand-chose, mais je n'en suis pas peu fier !
ça donne :

SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet],
IIf([OrdreTrajet]=1, "THIAIS",
DLookUp("[NomCommune]","[11-PlannificationVisiteSousForm]","[CléPersonnel]="
& [CléPersonnel] & " and [DateVisiteProf]=#" & [DateVisiteProf] & "# and
[OrdreTrajet]=" & [OrdreTrajet]
-1)) AS CommuneDépart, [NomCommune] AS CommuneArrivée FROM
[11-PlannificationVisiteSousForm]

UNION SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet]+1,
[NomCommune], "THIAIS"
FROM [11-PlannificationVisiteSousForm]D1
WHERE [OrdreTrajet]=(select max([OrdreTrajet]) from
[11-PlannificationVisiteSousForm]D2 WHERE D2.[CléPersonnel]Ñ.[CléPersonnel]
and D2.[DateVisiteProf]Ñ.[DateVisiteProf]);

4) Le code SQL de la requête [9-Etat de frais] devient
SELECT RequêteUnion2.*,
DLookUp("[Distance]","[TrajetsPetiteCouronne1]","[VilleDépart]='" &
[CommuneDépart] & "' and [VilleArrivée]='" & [CommuneArrivée]) & "'" AS
Distancier
FROM RequêteUnion2;
Mais ça ne marche pas mieux !
Avatar
Kolele
5) DL a écrit : Mais il serait beaucoup plus judicieux (et rapide !)
d'inclure la table Distancier dans la requête et de mettre une double
jointure à partir de CommuneDépart et de NomCommune (les champs s'appellent
aussi comme ça dans la table Distancier ?) : il resterait juste à mettre le
champ Distance dans la requête.

Je ne suis pas certain de bien lire ce plan B.
Lecture 1 : en mode modification, j'appelle la RequêteUNION2 et la table
TrajetsPetiteCouronne1 et je fais une jointure entre CommuneDépart et
VilleDépart ; j'en fais une autre entre CommuneArrivée et VilleArrivée.
Problème: ACCESS me retourne 2 trajets de retour pour chaque prof le même
jour !
Lecture 2 : se passer de la deuxième requête et de tout traiter à
l'intérieur de la RequêteUNION2. Mais là, plus d'interface graphique. Il va
falloir combiner UNON avec INNER JOIN ?
Ps : j'ai enfin acheté un manuel SQL, pour mourir un jour moins idiot (même
si ça va être long !)
Avatar
db
Kolele a écrit :
5) DL a écrit : Mais il serait beaucoup plus judicieux (et rapide !)
d'inclure la table Distancier dans la requête et de mettre une double
jointure à partir de CommuneDépart et de NomCommune (les champs s'appellent
aussi comme ça dans la table Distancier ?) : il resterait juste à mettre le
champ Distance dans la requête.

Je ne suis pas certain de bien lire ce plan B.
Lecture 1 : en mode modification, j'appelle la RequêteUNION2 et la table
TrajetsPetiteCouronne1 et je fais une jointure entre CommuneDépart et
VilleDépart ; j'en fais une autre entre CommuneArrivée et VilleArrivée.
Problème: ACCESS me retourne 2 trajets de retour pour chaque prof le même
jour !
Lecture 2 : se passer de la deuxième requête et de tout traiter à
l'intérieur de la RequêteUNION2. Mais là, plus d'interface graphique. Il va
falloir combiner UNON avec INNER JOIN ?
Ps : j'ai enfin acheté un manuel SQL, pour mourir un jour moins idiot (même
si ça va être long !)



Vu de loin, j'ai un peu de mal à voir pourquoi la Lecture 1 génère 2 trajets de retour. C'est systématique, ou seulement dans certains cas ? Parce que c'était effectivement à ça que je pensais. Essayez éventuellement - mais c'est bof, comme solution - de mettre la propriété Valeurs Distinctes à oui. Vous êtes sur de ne pas avoir de doublons dans votre table Distancier ?

db
Avatar
Kolele
Db,

1) J'ai collé ton code mais ça ne fonctionne pas encore. J'ai remplacé les
apostrophes par des parenthèses, pour voir : toujours le même message
d'erreur.

"erreur de syntaxe dans la chaîne dans l'expression
"[CommuneDépart]='THIAIS' and [NomCommune]='ORLY'"

2) Pour faire un peu d'ordre, je viens de donner des noms différents aux
champs de la table[TrajetsPetiteCouronne1]contenant les distances, pour plus
de clarté :

CléTrajet (type numéroauto)
VilleDépart (type texte)
VilleArrivée (type texte)
Distance (type numérique, réel double)

3) dans la requête UNION, je nomme le résultat de la fonction Dlookup :
[CommuneArrivée]
Ce n'est pas grand-chose, mais je n'en suis pas peu fier ! ça donne :

SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet],
IIf([OrdreTrajet]=1, "THIAIS",
DLookUp("[NomCommune]","[11-PlannificationVisiteSousForm]","[CléPersonnel]="
& [CléPersonnel] & " and [DateVisiteProf]=#" & [DateVisiteProf] & "# and
[OrdreTrajet]=" & [OrdreTrajet]
-1)) AS CommuneDépart, [NomCommune] AS CommuneArrivée FROM
[11-PlannificationVisiteSousForm]

UNION SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet]+1,
[NomCommune], "THIAIS"
FROM [11-PlannificationVisiteSousForm]D1
WHERE [OrdreTrajet]=(select max([OrdreTrajet]) from
[11-PlannificationVisiteSousForm]D2 WHERE D2.[CléPersonnel]Ñ.[CléPersonnel]
and D2.[DateVisiteProf]Ñ.[DateVisiteProf]);

4) Le code SQL de la requête [9-Etat de frais] devient
SELECT RequêteUnion2.*,
DLookUp("[Distance]","[TrajetsPetiteCouronne1]","[VilleDépart]='" &
[CommuneDépart] & "' and [VilleArrivée]='" & [CommuneArrivée]) & "'" AS
Distancier
FROM RequêteUnion2;
Mais ça ne marche pas mieux !

5) DL a écrit : Mais il serait beaucoup plus judicieux (et rapide !)
d'inclure la table Distancier dans la requête et de mettre une double
jointure à partir de CommuneDépart et de NomCommune (les champs s'appellent
aussi comme ça dans la table Distancier ?) : il resterait juste à mettre le
champ Distance dans la requête.

Je ne suis pas certain de bien lire ce plan B.
Lecture 1 : en mode modification, j'appelle la RequêteUNION2 et la table
TrajetsPetiteCouronne1 et je fais une jointure entre CommuneDépart et
VilleDépart ; j'en fais une autre entre CommuneArrivée et VilleArrivée.
Problème: ACCESS me retourne 2 trajets de retour pour chaque prof le même
jour !
Lecture 2 : se passer de la deuxième requête et de tout traiter à
l'intérieur de la RequêteUNION2. Mais là, plus d'interface graphique. Il va
falloir combiner UNON avec INNER JOIN ?
Ps : j'ai enfin acheté un manuel SQL, pour mourir un jour moins idiot (même
si ça va être long !)
Avatar
Michel__D
Bonjour,

Kolele a écrit :
Bonsoir à tous,
1)Michel, je te promets de regarder ton code, dès que j'en aurais fini avec
le précédent. Je débute en SQL, et il faut que j'y aille pas à pas
2) Toujours sur le même projet,
La requête union de db fonctionne comme sur des roulettes :

SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet],
IIf([OrdreTrajet]=1, "THIAIS",
DLookUp("[NomCommune]","[11-PlannificationVisiteSousForm]","[CléPersonnel]="
& [CléPersonnel] & " and [DateVisiteProf]=#" & [DateVisiteProf] & "# and
[OrdreTrajet]=" & [OrdreTrajet]
-1)) AS CommuneDépart, [NomCommune] FROM [11-PlannificationVisiteSousForm]

UNION SELECT [CléPersonnel], [DateVisiteProf], [OrdreTrajet]+1,
[NomCommune], "THIAIS"
FROM [11-PlannificationVisiteSousForm]D1
WHERE [OrdreTrajet]=(select max([OrdreTrajet]) from
[11-PlannificationVisiteSousForm]D2 WHERE D2.[CléPersonnel]Ñ.[CléPersonnel]
and D2.[DateVisiteProf]Ñ.[DateVisiteProf]);


Je veux faire ensuite une requête à partir de la précédente, reprenant tous
les champs, plus un champ calculer avec une fonction qui RechDom, pour aller
chercher dans une table la distance entre les CommuneDépart et NomCommune :

SELECT RequêteUnion2.*,
DLookUp("[Distance]","[TrajetsPetiteCouronne1]","[CommuneDépart]=" &
[CommuneDépart] & " and [NomCommune]=" & [NomCommune]) AS Distancier
FROM RequêteUnion2;

Msg d'erreur partout sur le champ calculé : "erreur de syntaxe (opérateur
absent) dans l'expression "[CommuneDépart]=ORLY and [NomCommune]=VITRY SUR
SEINE"

Que faire ?



Pour cette façon de procéder, db va surement te fournir la marche à
suivre, par contre voici ma nouvelle
proposition en 3 requêtes qui intégre la distance sachant que tu as les
tables suivantes :

[LaTable] qui possède les champs suivants :
[IdEnr], [IdProf], [DateVisite], [Commune]

et [LaTable2] qui possède les champs suivants (même si ce n'est pas
optimum) :
[IdEnr], [CommuneDep], [CommuneArr], [Distance]

Voici la 1ère requête "LaRequete"
PARAMETERS [Quel Prof ?] Long, [Quelle Date ?] DateTime;
SELECT T1.IdEnr, T1.IdProf, Format(T1.DateVisite,"yyyy/mm/dd") AS
DateVisite,
T1.Commune, Count(T2.IdEnr) AS Ordre
FROM LaTable AS T1 INNER JOIN LaTable AS T2
ON (T1.IdProf=T2.IdProf) AND (T1.DateVisite>=T2.DateVisite)
AND (Format(T1.DateVisite,"dd/mm/yyyy")=Format(T2.DateVisite,"dd/mm/yyyy"))
WHERE T1.IdProf=[Quel Prof ?] And
Format(T1.DateVisite,"dd/mm/yyyy")=[Quelle Date ?]
GROUP BY T1.IdEnr, T1.IdProf, Format(T1.DateVisite,"yyyy/mm/dd"),
T1.Commune;


Puis la requête unoin "LaRequeteU"
SELECT T.IdProf, T.DateVisite, "thiais" AS Depart, T.Commune AS Arrivee
FROM LaTable AS T INNER JOIN LaRequete AS R1 ON T.IdEnr = R1.IdEnr
WHERE R1.Ordre=1
UNION SELECT T.IdProf, T.DateVisite, R2.Commune, R1.Commune
FROM LaTable AS T INNER JOIN (LaRequete AS R1 INNER JOIN LaRequete AS R2
ON R1.IdProf = R2.IdProf And R1.DateVisite = R2.DateVisite And R1.Ordre
= R2.Ordre+1)
ON T.IdEnr = R1.IdEnr
WHERE R1.Ordre>1
UNION SELECT T.IdProf, DateAdd("s",1,T.DateVisite) AS DateVisite,
T.Commune AS Depart,
"thiais" AS Arrivee
FROM LaTable AS T INNER JOIN LaRequete AS R1 ON T.IdEnr=R1.IdEnr
WHERE R1.Ordre=(SELECT TOP 1 Ordre FROM LaRequete ORDER BY Ordre DESC);


Et enfin la requête finale
SELECT R.IdProf, R.DateVisite, R.Depart, R.Arrivee, T2.Distance
FROM LaRequeteU AS R INNER JOIN LaTable2 AS T2
ON (R.Depart=T2.CommuneDep And R.Arrivee=T2.CommuneArr)
OR (R.Depart=T2.CommuneArr And R.Arrivee=T2.CommuneDep)
ORDER BY R.IdProf, Format(R.DateVisite,"yyyy/mm/dd hh:mm:ss");
1 2