Mysql
 sql >> Database >  >> RDS >> Mysql

combinando i dati dei future mensili con le serie temporali del primo mese in MySQL

Ci vuole molto pre-controllo, ma in sostanza, ho dovuto costruire variabili SQL basate su un passaggio alla volta, come se fosse in un programma di "let X =qualcosa", "let y =X + qualcos'altro" , ecc. Costruendo la maggior parte delle variabili interne @SQLVars, una volta dichiarata la prima, può essere utilizzata come base della variabile successiva e così via... Innanzitutto, ecco la query completa che puoi applicare ai tuoi dati che compila in base a qualunque sia la data corrente. Se conosci meglio i tuoi dati, potresti doverli modificare un po', ma penso che questo ti metta sulla buona strada.

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

Il risultato di questa query sopra restituirà un SINGOLO record (basato sulla data corrente del 31 gennaio) per mostrare PrimoMese SecondoMese TerzoMese QuartoMeseQ (12 marzo) U (12 aprile) V (12 maggio) X (12 giugno)

Ora, nidifica questo nel resto della tua query per i tuoi ID ticker qualcosa come

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()

Se guardi le @SqlVariables più interne, come accennato in precedenza, è come un mucchio di "let x=something". Ho sempre bisogno di una base per iniziare, quindi ottengo prima il primo giorno di un determinato mese in una variabile @FirstOfMonth eseguendo una concatenazione di qualunque sia l'anno della data corrente + "-" + mese della data corrente + "-01" per iniziare sempre al primo del mese... es:Oggi è il 31 gennaio 2012 verrà creata una stringa di "2012-01-01" che nel formato anno/mese/data viene immediatamente riconosciuta da MySQL come formato della data possiamo eseguire l'aritmetica della data. Quindi ora ho @FirstOfMonth ='2012-01-01'. Ora, dobbiamo determinare il primo giorno della settimana che questa data rappresenta del mese in cui ci troviamo (da cui @FDOW). Questo restituirà un valore compreso tra 1 e 7 (domenica =1, mercoledì =4, sabato =7).

Da questo, ora dobbiamo calcolare quando sarà il secondo mercoledì del mese. Se il giorno della settimana va da domenica a (compreso) mercoledì, il SECONDO mercoledì è di 12 giorni MENO il giorno della settimana. Es:domenica 1 sarebbe mercoledì 4, poi mercoledì 11... quindi 12 - 1 (domenica) =11. Se il primo giorno del mese fosse mercoledì, sarebbe un giorno della settimana =4, ma il 1° del mese =mercoledì, secondo mercoledì =8, quindi 12 - 4 =8. Ora, se la data fosse gio, venerdì o sabato come primo del mese, il giorno della settimana sarebbe 5, 6 o 7 La data MINIMA del primo mercoledì sarebbe 7, il secondo mercoledì sarebbe 14, quindi inizia con 19 - qualunque giorno della settimana... 5, 6, 7... Es:19 - 5(gio giorno di settimana) =14, 19 - 6 (ven giorno della settimana) =13, 19 - 7 (sabato giorno della settimana) =12. Quindi, sappiamo che il primo mercoledì sarà l'intera settimana fuori, quindi il primo sarebbe be è 7° e 14° rispetto a 1° e 8° (primi mesi).

Ora che sappiamo QUANDO è il secondo mercoledì del mese, confrontalo con la data su cui stiamo eseguendo la query in base (ad esempio:curdate() ). Se la data corrente è ON o PRIMA (tramite <=) la SECONDA MERCOLEDI' del MESE (@SWOM), allora vogliamo solo saltare oltre 1 mese... se siamo più avanti nel mese, dobbiamo saltare 2 mesi.

Ora, costruisci le date. La base della data per il mese 1 è la prima del mese corrente PIÙ un intervallo di comunque molti mesi da saltare. Il mese 2 è un mese dopo il primo, il mese 3 uno dopo il mese 2 e il mese 4 uno dopo il mese 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 )

Quindi abbiamo finalmente tutti i 4 mesi di base con cui lavorare in una singola riga di ( select ... ) set di risultati sqlvars che mostrano qualcosa come

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

Infine, una volta che questi dati appaiono ok, ora possiamo costruire le stringhe specifiche che stai cercando con i rispettivi prefissi "Q", "U", "V" e "X" più il 3 sinistro del nome del mese con il 2 cifra anno.

Quindi, con questo ottenendo tutti gli intervalli di date e le stringhe che ti aspetti, esegui una query sull'altra tabella come ho elencato nell'iniziale.

Spero che questo ti aiuti e ti apra gli occhi su un contesto completamente nuovo in cui ingannare SQL... in sostanza facendo un programma inline per creare molte variabili e operare da quello... Abbastanza interessante eh...

E in tutta sincerità, questa è la prima volta che provo in modo specifico questa tecnica, anche se in passato ho eseguito molte query utilizzando SQLVars.