Mein bester Rat an Sie ist, tun Sie dies nicht. Das Speichern von Informationen, die aus anderen Informationen in der Datenbank abgeleitet werden können, wird im Allgemeinen als sehr schlechtes Design angesehen und der Versuch, sich auf die Reihenfolge der Zeilen in der Datenbank zu verlassen ist ein sicherer Weg in den Wahnsinn.
Hier ist ein erster Versuch, Ihre Tabelle zu normalisieren:
-- 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;
(Ich verfolge Baseball nicht, daher konnte ich einige der Spaltennamen nur erraten.) Beachten Sie, dass die year_id
, month_id
und day_id
Spalten sind weg, da diese Werte aus dem game_date
neu erstellt werden können Spalte, wie ich in den Kommentaren angegeben habe. Auch Ihre game_id
Spalte ist weg; Dies kann durch Verketten von opposing_team
neu erstellt werden , game_date
und game_seq
(was ich vermute, um doppelte Header &c. zu berücksichtigen.) Ich habe auch W
konvertiert und L
in eine einzelne Spalte, die die Werte "W" (Gewinn), "L" (Verlust) und "T" (Unentschieden) aufnehmen soll.
Die teams
table bietet eine Nachschlagetabelle für die 3-Zeichen-Team-IDs. Es kann erweitert werden, um beliebige andere Teamdaten zu speichern. (Beachten Sie, dass es das Team selbst; beschreiben soll Team Aktivitäten würde in eine andere Tabelle gehen.)
Um Ihre Frage zu den "constraint"-Klauseln zu beantworten, die erste (CONSTRAINT starting_pitcher_log_pk
und die eingerückte Zeile darunter) gibt an, dass die Verkettung dieser drei Spalten als primäre eindeutige Kennung für jede Zeile in der Tabelle dient. Der zweite (CONSTRAINT team_fk FOREIGN KEY (opposing_team)
und die eingerückten Zeilen darunter) bedeutet, dass ein Wert in opposing_team
platziert werden muss Spalte muss bereits existieren in teams.team_id
Säule; Du kannst nicht gegen ein Team spielen, das nicht existiert.
Jetzt arbeiten Sie daran, Ihre ursprüngliche Frage tatsächlich zu beantworten. Die beste Lösung, die ich für MySQL finden konnte, war eine Scratch-Tabelle und eine gespeicherte Prozedur wie folgt:
-- 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;
Und die gespeicherte Prozedur:
------------------------------------------------------------------------------ --
-- 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
Diese Prozedur löscht die Tabelle ip_subtotal
, füllt es aus der Haupttabelle und rollt dann die laufende Summe für die gepitchten Innings auf. Es verwendet auch eine einfache Steuerunterbrechung, um den Akkumulator zu Beginn des Jahres zurückzusetzen. Nachdem Sie die Prozedur ausgeführt haben, indem Sie
CALL accumulate_innings();
Sie können die ip_subtotal
abfragen Tabelle oder füge es wieder dem starting_pitchers_game_log
hinzu Tabelle wie gewünscht.
Das Verfahren könnte auch erweitert werden, um ein Start- und Enddatum zu akzeptieren; Ich überlasse das dem Leser als Übung.
Hoffe das hilft; es war interessant und zwang mich, ein wenig MySQL zu lernen.