Mysql
 sql >> Base de données >  >> RDS >> Mysql

combiner les données mensuelles des contrats à terme avec les séries chronologiques du premier mois dans MySQL

Cela demande beaucoup de pré-vérifications, mais en gros, j'ai dû construire des variables SQL basées sur une étape à la fois, comme si c'était dans un programme de "laissez X =quelque chose", "laissez y =X + quelque chose d'autre" , etc. En construisant les variables @SQLVars les plus internes, une fois la première déclarée, elle peut être utilisée comme base de la variable suivante et ainsi de suite... Tout d'abord, voici la requête complète que vous pouvez appliquer à vos données qui construit quelle que soit la date actuelle. Si vous connaissez mieux vos données, vous devrez peut-être les peaufiner, mais je pense que cela vous permettra d'avancer sur la bonne voie.

select
      CONCAT( 'Q (', LEFT( MonthName( DateBasis.dMonth1 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth1 ), 2 ), ')' ) as FirstMonth,
      CONCAT( 'U (', LEFT( MonthName( DateBasis.dMonth2 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth2 ), 2 ), ')' ) as SecondMonth,
      CONCAT( 'V (', LEFT( MonthName( DateBasis.dMonth3 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth3 ), 2 ), ')' ) as ThirdMonth,
      CONCAT( 'X (', LEFT( MonthName( DateBasis.dMonth4 ), 3 ), ' ', RIGHT( Year( DateBasis.dMonth4 ), 2 ), ')' ) as FourthMonth
   from   
      ( select @FirstOfMonth dFirstOfMonth,
               @FDOM nWeekDay,
               @SWOM nSecondWedOfMonth,
               @SkipMonths nSkip,
               @Month1 dMonth1,
               @Month2 dMonth2,
               @Month3 dMonth3,
               @Month4 dMonth4
           from
              ( select @FirstOfMonth := CONCAT( year(curdate()), '-', month( curdate()), '-01' ),
                       @FDOW := DayOfWeek( @FirstOfMonth ),
                       @SWOM := if( @FDOW <= 4, 12, 19) - @FDOW,
                       @SkipMonths := if( day( CurDate()) <= @SWOM, 1, 2 ),
                       @Month1 := date_add( @FirstOfMonth, interval 0 +  @SkipMonths month ),
                       @Month2 := date_add( @Month1, interval 1 month ),
                       @Month3 := date_add( @Month2, interval 1 month ),
                       @Month4 := date_add( @Month3, interval 1 month )
                       ) sqlvars
      ) DateBasis

Le résultat de cette requête ci-dessus renverra un enregistrement UNIQUE (basé sur la date actuelle du 31 janvier) pour afficherFirstMonth SecondMonth ThirdMonth FourthMonthQ (Mar 12) U (Apr 12) V (May 12) X (Jun 12)

Maintenant, imbriquez ceci dans le reste de votre requête pour vos identifiants de ticker quelque chose comme

SELECT hist.date, 
       hist.ticker_id, 
       hist.settle_price, 
       hist.volume 
   FROM 
      hist,
      ( entire select statement above ) FinalDates

   WHERE 
          hist.ticker_id IN ( FinalDates.FirstMonth,
                              FinalDates.SecondMonth,
                              FinalDates.ThirdMonth,
                              FinalDates.FourthMonth )
      and hist.trade_dt = curdate()

Si vous regardez les @SqlVariables les plus intimes comme mentionné précédemment, c'est comme un tas de "laisser x=quelque chose". J'ai toujours besoin d'une base pour commencer, donc je commence par obtenir le premier jour d'un mois donné dans une variable @FirstOfMonth en faisant une concaténation de l'année de la date actuelle + "-" + mois de la date actuelle + "-01" pour toujours commencer par le premier du mois... ex :Aujourd'hui est le 31 janvier 2012 construira une chaîne de '2012-01-01' qui au format année/mois/date est immédiatement reconnu par MySQL en tant que format de date sur lequel nous pouvons effectuer une arithmétique de date. Alors maintenant, j'ai @FirstOfMonth ='2012-01-01'. Maintenant, nous devons déterminer le premier jour de la semaine que cette date représente du mois dans lequel nous nous trouvons (d'où @FDOW). Cela renverra une valeur de 1 à 7 (dimanche =1, mer =4, sam =7).

À partir de là, nous devons maintenant calculer quand sera le 2e mercredi du mois. Si le jour de la semaine va du dimanche au mercredi (inclus), le DEUXIÈME mercredi correspond à 12 jours MOINS le jour de la semaine. Ex :Dimanche 1er serait Mer 4, puis Mer 11... donc 12 - 1 (Dimanche) =11. Si le premier jour du mois ÉTAIT un Mer, ce serait un jour de la semaine =4, mais le 1er du mois =mer, le deuxième mer =8, donc 12 - 4 =8. Maintenant, si la date était jeudi, vendredi ou samedi comme premier du mois, le jour de la semaine serait un 5, 6 ou 7 La date MINIMUM du premier mercredi serait 7, le deuxième mercredi serait 14, donc cela commence par 19 - quel que soit le jour de la semaine... 5, 6, 7... Ex :19 - 5 (jeu jour du semaine) =14, 19 - 6 (vendredi jour de la semaine) =13, 19 - 7 (samedi jour de la semaine) =12. Nous savons donc que le premier mercredi sera la semaine complète, donc le plus tôt ce serait be est le 7e et le 14e et non le 1er et le 8e (le plus tôt du mois).

Maintenant que nous savons QUAND est le 2e mercredi du mois, comparez cela à la date à laquelle nous exécutons la requête (c'est-à-dire:curdate() ). Si la date actuelle est LE ou AVANT (via <=) le DEUXIÈME MER du MOIS (@SWOM), alors nous ne voulons sauter que 1 mois... si nous sommes plus loin dans le mois, nous devons sauter 2 mois.

Maintenant, établissez les dates. La base de date pour le mois 1 est le premier du mois en cours PLUS un intervalle de plusieurs mois à ignorer. Le mois 2 est un mois après le premier, le mois 3 un mois après le mois 2 et le mois 4 un mois après le mois 3.

@FirstOfMonth := CONCAT( year(curdate()), '-', month( curdate()), '-01' ),
@FDOW := DayOfWeek( @FirstOfMonth ),
@SWOM := if( @FDOM <= 4, 12, 19) - @FDOM,
@SkipMonths := if( day( CurDate()) <= @SWOM, 1, 2 ),
@Month1 := date_add( @FirstOfMonth, interval 0 +  @SkipMonths month ),
@Month2 := date_add( @Month1, interval 1 month ),
@Month3 := date_add( @Month2, interval 1 month ),
@Month4 := date_add( @Month3, interval 1 month )

Nous avons donc enfin la base de 4 mois avec laquelle travailler dans une seule ligne de (sélectionnez ... ) ensemble de résultats sqlvars montrant quelque chose comme

@Month1     @Month2     @Month3     @Month4
2012-03-01  2012-04-01  2012-05-01  2012-06-01 ... the four months out

Enfin, une fois que ces données semblent correctes, nous pouvons maintenant créer les chaînes spécifiques que vous recherchez avec les préfixes "Q", "U", "V" et "X" respectifs plus le 3 gauche du nom du mois avec le 2 chiffres de l'année.

Donc, avec cela pour obtenir toutes les plages de dates et les chaînes que vous attendez, interrogez-les par rapport à votre autre table comme je l'ai indiqué dans l'initial.

J'espère que cela vous aidera et vous ouvrira les yeux sur un contexte complètement nouveau pour tromper SQL... essentiellement faire un programme en ligne pour créer de nombreuses variables et fonctionner à partir de cela... Plutôt cool hein...

Et en toute honnêteté, c'est la première fois que j'essaie spécifiquement cette technique, même si j'ai déjà effectué de nombreuses requêtes à l'aide de SQLVars.