Un membre du forum voulait savoir depuis quand des actions boursières avaient obtenu leur cours actuel…
Fonction VBA pour créer la table et les enregistrements
Const cInsert As String = "INSERT INTO tAction (Action, CoursDate, CoursValeur) VALUES "
With DoCmd
.SetWarnings False
.RunSQL "CREATE TABLE tAction (Action CHAR, CoursDate DATE, CoursValeur DOUBLE, " & _
"CONSTRAINT PrimaryKey PRIMARY KEY (Action, CoursDate));"
.RunSQL cInsert & "('A', '27/04/2012', 10);"
.RunSQL cInsert & "('A', '25/04/2012', 9);"
.RunSQL cInsert & "('A', '26/04/2012', 10);"
.RunSQL cInsert & "('A', '28/04/2012', 10);"
.RunSQL cInsert & "('B', '11/04/2012', 4);"
.RunSQL cInsert & "('B', '09/04/2012', 4);"
.RunSQL cInsert & "('B', '10/04/2012', 5);"
.SetWarnings True
End With
MsgBox "Création terminée"
End Function
La requête SQL
MAX(T1.CoursDate) AS MaxDate,
MIN(T1.CoursDate) AS MinDate,
T1.CoursValeur
FROM tAction AS T1
WHERE T1.CoursValeur = ALL
(SELECT CoursValeur
FROM tAction T2
WHERE T2.Action = T1.Action
AND
T2.CoursDate >= T1.CoursDate
)
GROUP BY T1.Action,
T1.CoursValeur;
Les Résultats
A 28/04/2012 26/04/2012 10
B 11/04/2012 11/04/2012 4
Explications
La difficulté est de trouver la première date pour laquelle le cours soit identique au cours actuel ET qu’entre-temps aucun cours ne soit différent…
Tout se passe dans la clause WHERE…
On ne retient que les lignes qui ont un cours égal à TOUTES ((opérateur de comparaison ALL)) les lignes qui ont un cours plus récent que la date de la ligne courant (T1.CoursDate).
En effet, la sous-requête conditionnelle (appelée conditionnelle car sa clause WHERE utilise des données liées à la table T1 qui sont des prédicats prédéfinis)
FROM tAction T2
WHERE T2.Action = T1.Action
AND
T2.CoursDate >= T1.CoursDate
retourne toutes les lignes de la table tAction qui ont une date supérieure ou égale à la date de la ligne courante pour l’action courante.
Si le cours de la ligne courante n’est pas égal à l’ensemble des cours de la sous requête, alors la ligne n’est pas retournée.
Finalement, sur ce jeu filtré de lignes, les fonctions d’agrégation Max(), Min() retourne la date maxi et la date mini pour chaque action et pour chaque cours (GROUP BY Action, CoursValeur). Vu que CoursValeur est unique depuis le filtre, on obtient bien que la période la plus récente ayant le même cours pour chaque action.
Remarque
La sous-requête conditionnelle réclame un temps de traitement long qui augmente avec le nombre de lignes de la table.
@+
Philippe