あなたへの私の最善のアドバイスは、これをしないでください。データベース内の他の情報から派生する可能性のある情報を格納することは、一般に非常に貧弱な設計と見なされ、データベース内の行の順序に依存しようとします 狂気への確かな道です。
テーブルを正規化するための最初のパスは次のとおりです。
-- Table: teams
-- DROP TABLE teams;
CREATE TABLE teams
(
team_id character(3) primary key,
team_name varchar(255),
team_city varchar(255)
) engine=innodb;
-- Table: starting_pitchers_game_log
-- DROP TABLE starting_pitchers_game_log;
CREATE TABLE starting_pitchers_game_log
(
pitcher_id character(10) NOT NULL,
game_date date NOT NULL,
opposing_team character(3),
game_seq integer NOT NULL,
outcome character(1),
innings_pitched real,
bfp integer,
hits integer,
runs integer,
errors integer,
homeruns integer,
bb integer,
k integer,
ibb integer,
hbp integer,
wp integer,
balks integer,
CONSTRAINT starting_pitcher_log_pk
PRIMARY KEY (pitcher_id , game_date , game_seq ),
CONSTRAINT team_fk FOREIGN KEY (opposing_team)
REFERENCES teams (team_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
) engine=innodb;
(私は野球をフォローしていないので、列名の一部しか推測できませんでした。)year_id
に注意してください。 、month_id
およびday_id
これらの値はgame_date
から再作成できるため、列はなくなりました。 コメントで示したように列。また、game_id
列がなくなりました。これは、opposing_team
を連結することで再現できます。 、game_date
およびgame_seq
(これは、ダブルヘッダーなどを説明するためのものだと思います。)W
も変換しました およびL
値「W」(勝ち)、「L」(負け)、および「T」(引き分け)を保持することを目的とした単一の列に。
teams
tableは、3文字のチームIDのルックアップテーブルを提供します。必要な他のチームデータを保持するように拡張できます。 (チーム自体を説明するためのものであることに注意してください。 チームアクティビティ 別のテーブルに入れます。)
「制約」句に関する質問に答えるには、最初の句(CONSTRAINT starting_pitcher_log_pk
その下のインデントされた行)は、これら3つの列の連結が、テーブルの各行の主要な一意の識別子として機能することを示しています。 2番目のもの(CONSTRAINT team_fk FOREIGN KEY (opposing_team)
その下のインデントされた行)は、値がopposing_team
に配置されることを意味します 列それはすでに存在している必要があります teams.team_id
内 桁;存在しないチームと対戦することはできません。
次に、元の質問に実際に答えることに取り組みます。 MySQLで思いついた最善の解決策は、次のようなスクラッチテーブルとストアドプロシージャでした。
-- Table: ip_subtotal
-- DROP TABLE ip_subtotal;
CREATE TABLE ip_subtotal
(
pitcher_id char(10) NOT NULL,
game_date date NOT NULL,
game_seq int(11) NOT NULL,
innings_pitched double,
ip_total double DEFAULT '0.0',
CONSTRAINT ip_subtotal_pk
PRIMARY KEY (pitcher_id , game_date , game_seq )
) ENGINE=InnoDB;
そしてストアドプロシージャ:
------------------------------------------------------------------------------ --
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE PROCEDURE accumulate_innings()
BEGIN
DECLARE pit_id CHAR(10);
DECLARE gdate DATE;
DECLARE seq INT;
DECLARE in_pit REAL;
DECLARE accum REAL;
DECLARE prev_year YEAR(4);
DECLARE end_of_cursor BOOLEAN;
DECLARE c1 CURSOR FOR
SELECT pitcher_id, game_date, game_seq, innings_pitched
FROM ip_subtotal
ORDER BY pitcher_id, game_date, game_seq;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET end_of_cursor := TRUE;
TRUNCATE TABLE ip_subtotal;
INSERT INTO ip_subtotal
SELECT pitcher_id, game_date, game_seq, innings_pitched, 0.0
FROM starting_pitchers_game_log;
SET prev_year := 0;
OPEN c1;
fetch_loop: LOOP
FETCH c1 INTO pit_id, gdate, seq, in_pit;
IF end_of_cursor THEN
LEAVE fetch_loop;
END IF;
IF YEAR(gdate) != prev_year THEN
SET accum := 0.0;
SET prev_year := YEAR(gdate);
END IF;
SET accum := accum + in_pit;
UPDATE ip_subtotal
SET ip_total = accum
WHERE pitcher_id = pit_id
AND game_date = gdate
AND game_seq = seq;
END LOOP;
CLOSE c1;
END
この手順により、テーブルip_subtotal
がクリアされます。 、メインテーブルからデータを入力し、投球回の現在の合計をロールアップします。また、単純なコントロールブレークを使用して、年の初めにアキュムレータをリセットします。実行してプロシージャを実行した後
CALL accumulate_innings();
ip_subtotal
をクエリできます テーブルまたはstarting_pitchers_game_log
に結合し直します 必要に応じてテーブルを作成します。
手順を拡張して、開始日と終了日を受け入れることもできます。読者の練習問題として残しておきます。
お役に立てれば;それは面白くて、MySQLを少し学ぶことを余儀なくされました。