5

次の表を更新するために、いくつかのヘルプ(できればダミーのガイド)を使用できます。

CREATE TABLE `SYMBOL` (
  `day` date NOT NULL,
  `open` decimal(8,3) DEFAULT NULL,
  `high` decimal(8,3) DEFAULT NULL,
  `low` decimal(8,3) DEFAULT NULL,
  `close` decimal(8,3) DEFAULT NULL,
  `volume` bigint(20) DEFAULT NULL,
  `adj_close` decimal(8,3) DEFAULT NULL,
  `moving_average` decimal(8,3) DEFAULT NULL,
  PRIMARY KEY (`day`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

moving_average 列は現在空です。他のすべての列が入力されます (当面は、これが「静的」であっても問題ありません。行を追加するときに更新する必要はありませんが、これが簡単に実行できるのであれば、それは素晴らしいことです)。計算したいのは20日移動平均です。

ここの手順をできる限り実行してみました。

MySQL を使用して移動平均を計算するにはどうすればよいですか?

私のクエリはこれです:

SELECT
     `close`,
     (
     SELECT
          AVG(`close`) AS moving_average
     FROM
          SYMBOL T2
     WHERE
          (
               SELECT
                    COUNT(*)
               FROM
                    SYMBOL T3
               WHERE
                    `day` BETWEEN T2.day AND T1.day
          ) BETWEEN 1 AND 20
     )
FROM
     SYMBOL T1

クエリを正しく変更しましたか? 結果をmoving_average列に書き込むために何をする必要がありますか?

上記を実行すると、何も起こりません(実行中、エラーなし、長時間実行した後、停止したと表示されます)。列 moving_average にはまだ NULL 値があります。

この回答も見ました: MySQLで複数の移動平均を計算する方法

ただし、テーブルの返信に何を変更する必要があるのか​​ わかりません。

どんな助けでも大歓迎です。

4

2 に答える 2

2

これには 2 つの方法があります。

  1. updateテーブルのすべての行を更新するクエリを作成する
  2. ジョブを実行するストアド プロシージャを作成する

私は個人的にオプション 2 を好みます。

delimiter $$
create procedure movingAvg()
begin
    declare mv double;
    declare t date;
    declare done int default false;
    declare cur_t cursor for
         select distinct day from symbol
         order by day;
    declare cur_mv cursor for
         select avg(close) from symbol
         where day between date_add(t, interval -19 day) and t;
         -- Here you define the interval of your MV.
         -- If you want a 20-day MV, then the interval is between t-19 and t
    declare continue handler for not found set done=true;

    open cur_t;
    loop_day: loop
        fetch cur_t into t;
        if not done then
            open cur_mv;
            fetch cur_mv into mv;
            close cur_mv;
            update SYMBOL
                set moving_average = mv
                where day=t;
        else
            leave loop_day;
        end if;
    end loop loop_day;
    close cur_t;
end;
delimiter ;
于 2012-10-21T13:56:49.783 に答える
0

考えられる解決策は次のとおりです。

update SYMBOLS
from (
   select a.day
        , avg(b.close) as moving_average
   from   SYMBOLS a
   cross join SYMBOLS b
   where b.day BETWEEN date_sub(a.day, INTERVAL 19 DAY) and a.day
      and a.moving_average is null
   group by a.day
   ) x
set moving_average=x.moving_average
where SYMBOLS.day=x.day

申し訳ありませんが、私は自分でmysqlを使用していないため、日付の算術構文を推測しています。そして、あなたmoving_averageが null である行のみを更新する条件を追加しました。

更新:このソリューションは 365 日のカレンダーに基づいていることをご理解ください。「20 日」や「30 日」などのほとんどの株式市場平均は、週末と祝日を除く取引カレンダーに基づいています。自分で取引カレンダー テーブル (すべての取引日の単純なリスト) を作成する必要があります。それをしたい場合は、その趣旨で新しい質問をすることをお勧めします。

于 2012-10-21T17:06:13.190 に答える