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

MySQLはN行の移動平均を計算します

    計画

    クエリ

    select curr.date, curr.security_id, avg(prev.close)
    from history curr
    inner join history prev 
    on prev.`date` between date_sub(curr.`date`, interval 49 day) and curr.`date`
    and curr.security_id = prev.security_id
    group by 1, 2
    order by 2, 1
    ;
    

    出力

    +---------------------------+-------------+--------------------+
    |           date            | security_id |  avg(prev.close)   |
    +---------------------------+-------------+--------------------+
    | January, 04 2016 00:00:00 | 1           | 10.770000457763672 |
    | January, 05 2016 00:00:00 | 1           | 10.800000190734863 |
    | January, 06 2016 00:00:00 | 1           | 10.673333485921225 |
    | January, 07 2016 00:00:00 | 1           | 10.59250020980835  |
    | January, 08 2016 00:00:00 | 1           | 10.432000160217285 |
    | January, 11 2016 00:00:00 | 1           | 10.40166680018107  |
    | January, 12 2016 00:00:00 | 1           | 10.344285828726631 |
    | January, 13 2016 00:00:00 | 1           | 10.297500133514404 |
    | January, 14 2016 00:00:00 | 1           | 10.2877779006958   |
    | January, 04 2016 00:00:00 | 2           | 56.15999984741211  |
    | January, 05 2016 00:00:00 | 2           | 56.18499946594238  |
    | ..                        | ..          | ..                 |
    +---------------------------+-------------+--------------------+
    

    sqlfiddle

    参照

    最後の50行を使用するように変更

    select
    rnk_curr.`date`, rnk_curr.security_id, avg(rnk_prev50.close)
    from
    (
    select `date`, security_id,
    @row_num := if(@lag = security_id, @row_num + 1,
                   if(@lag := security_id, 1, 1)) as row_num
    from history 
    cross join ( select @row_num := 1, @lag := null ) params
    order by security_id, `date`
    ) rnk_curr
    inner join
    (
    select date, security_id, close,
    @row_num := if(@lag = security_id, @row_num + 1,
                   if(@lag := security_id, 1, 1)) as row_num
    from history 
    cross join ( select @row_num := 1, @lag := null ) params
    order by security_id, `date`
    ) rnk_prev50
    on  rnk_curr.security_id = rnk_prev50.security_id
    and rnk_prev50.row_num between rnk_curr.row_num - 49 and rnk_curr.row_num
    group by 1,2
    order by 2,1
    ;
    

    sqlfiddle

    if関数は、変数の評価の正しい順序を強制することです。



    1. SQLServer2012のプロセッサの選択

    2. MySQLの多対多の関係

    3. Laravel 4:存在しない場所

    4. Postgres/SQLAlchemyでのapplication_nameの設定