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.