sql >> データベース >  >> RDS >> Mysql

MySQLで毎月の先物データを前月の時系列に結合する

    多くの事前チェックが必要ですが、本質的には、「let X =something」、「let y =X + somethingelse」のプログラムのように、一度に1つのステップに基づいてSQL変数を作成する必要がありました。 、など。最も内側の@SQLVars変数を構築することにより、最初の変数が宣言されると、次の変数の基礎として使用できるようになります。最初に、構築するデータに適用できる完全なクエリを次に示します。現在の日付に基づいています。データをよく知っていると、データを微調整する必要があるかもしれませんが、これでうまくいくと思います。

    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
    

    上記のこの1つのクエリの結果は、(1月31日の現在の日付に基づく)SINGLEレコードを返し、FirstMonth SecondMonth ThirdMonth FourMonthQ(3月12日)U(4月12日)V(5月12日)X(6月12日)

    次に、これを残りのクエリ内にネストして、ティッカーIDを次のようにします

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

    前述のように最も内側の@SqlVariablesを見ると、「let x=something」の束のようなものです。私は常に開始するための基礎が必要なので、最初に、現在の日付の年+ "-" +現在の日付の月+を連結して、特定の月の最初の日を変数@FirstOfMonthに入れます。 「-01」は常に月の最初から始まります...例:今日は2012年1月31日で、「2012-01-01」の文字列が作成されます。この文字列は、年/月/日付の形式でMySQLによってすぐに認識されます。日付形式として、日付演算を実行できます。だから今、私は@FirstOfMonth='2012-01-01'を持っています。ここで、この日付が現在の月を表す最初の曜日を決定する必要があります(したがって、@ FDOW)。これにより、1〜7の値が返されます(日曜日=1、水=4、土=7)。

    これから、その月の第2水曜日がいつになるかを計算する必要があります。曜日が日曜日から水曜日(およびそれを含む)の場合、第2水曜日は12日マイナス曜日です。例:日曜日の1日は水曜日の4日、次に水曜日の11日...したがって12-1(日曜日)=11。月の最初の日が水曜日の場合、曜日=4になりますが、月の1日=水、2番目の水=8、つまり12-4 =8。ここで、日付が月の最初として木、金、または土である場合、曜日は5、6、または7になります。 。第1水曜日の最小日付は7、第2水曜日は14になるため、これは19から始まります-どの曜日でも... 5、6、7 ...例:19-5(木曜日週)=14、19-6(金曜日)=13、19-7(土曜日)=12 ..したがって、最初の水曜日が丸1週間になることがわかっているので、最も早い水曜日になります。 beは1日と8日(月の初め)ではなく7日と14日です。

    月の第2水曜日がいつであるかがわかったので、それに基づいてクエリを実行している日付と比較します(つまり、curdate())。現在の日付がONまたはその前(<=を介して)の第2水曜日(@SWOM)の場合、1か月をスキップするだけです...その月がさらに進んでいる場合は、2か月をスキップする必要があります。

    次に、日付を作成します。 1か月目の日付基準は、当月の最初に加えて、スキップする月数の間隔です。 2か月目は、最初の1か月後、3か月目は2か月目から1か月後、4か月目は3か月目から1か月後です。

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

    したがって、最終的には、(select ...)sqlvars結果セットの1行で4か月すべてを処理して、次のようなものを表示することができます

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

    最後に、このデータに問題がないことを確認したら、それぞれの「Q」、「U」、「V」、「X」のプレフィックスに加えて、月の名前の左3に2を付けて、探している特定の文字列を作成できます。桁の年。

    したがって、これで期待するすべての日付範囲と文字列を取得したら、最初にリストしたように、他のテーブルに対してこれをクエリします。

    これがお役に立てば幸いです。SQLをだまして...本質的にはインラインプログラムを実行して多くの変数を作成し、そこから操作するためのまったく新しいコンテキストに目を向けてください...かなりクールですね...

    正直なところ、SQLVarsを使用して過去に多くのクエリを実行したことがありますが、この手法を具体的に試したのはこれが初めてです。




    1. postgresの日付表現をISO8601文字列に変換します

    2. DatagridviewにMySQLデータを入力します

    3. SQL別のテーブルから合計して別のテーブルに挿入する方法

    4. MariaDBでのFROM_DAYS()のしくみ