Requête SQL sur actions boursières

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

Public Function CreationTableAction()
   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

SELECT    T1.Action,
          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

Action  MaxDate    MinDate    CoursValeur
  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)

SELECT  CoursValeur
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

Laisser un commentaire