この質問とその回答は、 2つのプロシージャのそれぞれが独自のテーブルにデータを入力するのではなく、2つのプロシージャを1つに組み合わせて1つのテーブルにデータを入力するにはどうすればよいですか?
および
「ピッチャー休憩時間」と「防御率」の計算は独立しているので、それぞれ別の手順をお勧めします。ただし、2つの手順の結果は一緒に使用されることが多いため、計算には一般的なスクラッチテーブルをお勧めし、リファクタリング そのスクラッチテーブルの作成と作成を3番目の手順に:
DELIMITER $$
-- DROP PROCEDURE pitcher_stats_reset $$
CREATE PROCEDURE pitcher_stats_reset()
BEGIN
DROP TEMPORARY TABLE IF EXISTS pitcher_stats_temp;
CREATE TEMPORARY TABLE pitcher_stats_temp
(
pitcher_id char(10) NOT NULL,
game_date date NOT NULL,
game_seq int NOT NULL,
innings_pitched double DEFAULT 0.0,
ip_total double DEFAULT 0.0,
earned_runs INT DEFAULT 0,
er_total INT DEFAULT 0,
std_era DOUBLE DEFAULT 0.0,
starter_rest INT DEFAULT 0,
CONSTRAINT pitcher_stats_temp_pk
PRIMARY KEY (pitcher_id , game_date , game_seq )
) ENGINE=InnoDB;
INSERT INTO pitcher_stats_temp
(pitcher_id, game_date, game_seq, innings_pitched, earned_runs)
SELECT pitcher_id, game_date, game_seq,
IFNULL(innings_pitched, 0), -- replace NULL with 0, if
IFNULL(runs, 0) -- column not initialized
FROM starting_pitchers_game_log;
END $$
DELIMITER ;
以前のバージョンでは、MySQLによる一時テーブルの処理にまだ慣れていなかったため、通常の永続テーブルを使用していました。ユーザーがログオフすると、一時テーブルが自動的に削除され、必要に応じて再生成できる派生データに使用されたスペースが再利用されます。テーブルを削除して再作成することは、TRUNCATE
と同等です。 ing(テーブルが事前に存在する必要がないことを除く)は、無条件のDELETE
よりもはるかに高速です。 、MySQLドキュメントによると。 防御率
同様に。
ピッチャーの休憩時間を計算する手順は、再び標準の「コントロールブレイク」イディオムに従います。ループに入る前に最初のレコードを読み取り、制御フィールドを1回設定してから、ループ内で終了条件をテストし、「現在の」レコードを処理し、「次の」レコードを読み取ってループすることに注意してください。
>DROP PROCEDURE IF EXISTS pitcher_stats_rest_time;
DELIMITER $$
CREATE PROCEDURE pitcher_stats_rest_time()
BEGIN
DECLARE pit_id CHAR(10);
DECLARE prev_pit CHAR(10);
DECLARE gdate DATE;
DECLARE seq INT;
DECLARE prev_date DATE;
DECLARE rest_days INT;
DECLARE end_of_cursor BOOLEAN;
DECLARE no_table CONDITION FOR SQLSTATE '42S02';
DECLARE c1 CURSOR FOR
SELECT pitcher_id, game_date, game_seq
FROM pitcher_stats_temp
ORDER BY pitcher_id, game_date, game_seq;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET end_of_cursor := TRUE;
DECLARE EXIT HANDLER FOR no_table
BEGIN
SIGNAL no_table
SET MESSAGE_TEXT = "Work table not initialized. Please call pitcher_stats_reset() before continuing",
MYSQL_ERRNO = 1146;
END;
SET end_of_cursor := FALSE;
-- Read first record and initialize control fields
OPEN c1;
FETCH c1 INTO pit_id, gdate, seq;
SET prev_date := 0;
SET prev_pit := pit_id;
fetch_loop: LOOP
-- Test for end-of-cursor
IF end_of_cursor THEN
LEAVE fetch_loop;
END IF;
-- Test for change in control fields. If the pitcher changes,
-- fake a change in the year to trigger the break.
IF pit_id != prev_pit THEN
SET prev_date := 0;
END IF;
IF YEAR(prev_date) = YEAR(gdate) THEN
SET rest_days := DATEDIFF(gdate, prev_date);
ELSE
SET rest_days := 0;
END IF;
UPDATE pitcher_stats_temp
SET starter_rest = rest_days
WHERE pitcher_id = pit_id
AND game_date = gdate
AND game_seq = seq;
-- After processing record, update control fields
SET prev_date := gdate;
SET prev_pit := pit_id;
-- Read next record and repeat
FETCH c1 INTO pit_id, gdate, seq;
END LOOP;
CLOSE c1;
END $$
DELIMITER ;
使用中、pitcher_stats_reset()
作業テーブルを初期化するために、最初に呼び出されます。それが完了したら、pitcher_stats_era()
およびpitcher_stats_rest_time()
任意の順序で繰り返し呼び出すことができます。 pitcher_stats_reset()
の場合 が最初に呼び出されない場合、他の2つの手順は、そうするように丁寧なリマインダーを発行します。