Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Kombinieren monatlicher Futures-Daten mit Front-Month-Zeitreihen in MySQL

Es erfordert viel Vorabprüfung, aber im Wesentlichen musste ich SQL-Variablen basierend auf einem Schritt nach dem anderen erstellen, als ob es in einem Programm von „let X =something“, „let y =X + somethingelse“ wäre. usw. Durch Erstellen der innersten @SQLVars-Variablen kann diese, sobald die erste deklariert ist, als Grundlage für die nächste Variable verwendet werden usw. Hier ist zunächst die vollständige Abfrage, die Sie auf Ihre zu erstellenden Daten anwenden können basierend auf dem aktuellen Datum. Wenn Sie Ihre Daten besser kennen, müssen Sie sie vielleicht etwas optimieren, aber ich denke, das bringt Sie auf einen guten Weg.

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

Das Ergebnis dieser einen Abfrage oben gibt einen EINZELNEN Datensatz (basierend auf dem aktuellen Datum 31. Januar) an showFirstMonth SecondMonth ThirdMonth FourthMonthQ (12. März) U (12. April) V (12. Mai) X (12. Juni)

zurück

Verschachteln Sie dies nun in den Rest Ihrer Abfrage für Ihre Ticker-IDs, etwa so wie

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

Wenn Sie sich die innersten @SqlVariablen ansehen, wie zuvor erwähnt, ist dies wie ein Haufen von "let x=something". Ich brauche immer eine Basis, um zu beginnen, also bringe ich zuerst den ersten Tag eines bestimmten Monats in eine Variable @FirstOfMonth, indem ich eine Verkettung des Jahres des aktuellen Datums + "-" + Monat des aktuellen Datums + mache "-01", um immer am ersten des Monats zu beginnen ... Beispiel:Heute ist der 31. Januar 2012 wird eine Zeichenfolge von "2012-01-01" erstellt, die im Format Jahr/Monat/Datum sofort von MySQL erkannt wird als Datumsformat können wir Datumsarithmetik durchführen. Jetzt habe ich also @FirstOfMonth ='2012-01-01'. Jetzt müssen wir den ersten Wochentag bestimmen, den dieses Datum des Monats darstellt, in dem wir uns befinden (daher @FDOW). Dies gibt einen Wert von 1-7 zurück (Sonntag =1, Mi =4, Sa =7).

Daraus müssen wir nun berechnen, wann der 2. Mittwoch des Monats sein wird. Wenn der Wochentag Sonntag bis (einschließlich) Mittwoch ist, beträgt der ZWEITE Mittwoch 12 Tage MINUS dem Wochentag. Beispiel:Sonntag, der 1., wäre Mi, der 4., dann Mi, der 11. ... also 12 - 1 (Sonntag) =11. Wenn der erste Tag des Monats ein Mi WÄRE, wäre es ein Wochentag =4, aber der Der 1. des Monats =Mi, der zweite Mi =8, also 12 - 4 =8. Wenn das Datum Do, Fr oder Sa als Erster des Monats wäre, wäre der Wochentag eine 5, 6 oder 7 . Das MINDEST-Datum des ersten Mittwochs wäre 7, das zweite Mi wäre 14, also beginnt es mit 19 - egal an welchem ​​Wochentag ... 5, 6, 7 ... Bsp.:19 - 5 (Do Day of Woche) =14, 19 - 6 (Freitag der Woche) =13, 19 - 7 (Samstag der Woche) =12.. Wir wissen also, dass der erste Mittwoch die ganze Woche aus sein wird, also der früheste be ist der 7. und 14. im Gegensatz zum 1. und 8. (frühester Monat).

Jetzt, da wir wissen, WANN der 2. Mittwoch des Monats ist, vergleichen Sie das mit dem Datum, auf dem wir die Abfrage basierend auf (dh:curdate() ) ausführen. Wenn das aktuelle Datum AN oder VOR (über <=) dem ZWEITEN MI des MONATS (@SWOM) ist, dann wollen wir nur 1 Monat überspringen... wenn wir weiter im Monat sind, müssen wir 2 Monate überspringen.

Bauen Sie jetzt die Daten aus. Die Datumsbasis für Monat 1 ist der Erste des aktuellen Monats PLUS ein Intervall von beliebig vielen zu überspringenden Monaten. Monat 2 liegt einen Monat nach dem ersten, Monat 3 einen nach Monat 2 und Monat 4 einen nach Monat 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 )

Wir haben also endlich alle 4 Monate, mit denen wir in einer einzigen Reihe von ( select ... ) sqlvars-Ergebnissätzen arbeiten können, die so etwas wie

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

Schließlich, sobald diese Daten in Ordnung erscheinen, können wir jetzt die spezifischen Zeichenfolgen, nach denen Sie suchen, mit den jeweiligen Präfixen „Q“, „U“, „V“ und „X“ sowie der linken 3 des Monatsnamens mit der 2 erstellen Ziffer Jahr.

Wenn Sie also alle Datumsbereiche und Zeichenfolgen erhalten, die Sie erwarten, fragen Sie dies mit Ihrer anderen Tabelle ab, wie ich in der Initiale aufgeführt habe.

Ich hoffe, das hilft Ihnen und öffnet Ihnen die Augen für einen völlig neuen Kontext, um SQL dazu zu bringen ... im Wesentlichen ein Inline-Programm zu erstellen, um viele Variablen zu erstellen und davon zu operieren ... Ziemlich cool, huh ...

Und ehrlich gesagt ist dies das erste Mal, dass ich diese Technik speziell ausprobiert habe, obwohl ich in der Vergangenheit viele Abfragen mit SQLVars durchgeführt habe.