Il mio miglior consiglio per te è:non farlo. L'archiviazione delle informazioni che possono essere derivate da altre informazioni nel database è generalmente considerata una progettazione molto scadente e il tentativo di fare affidamento sull'ordine delle righe nel database è un percorso sicuro verso la follia.
Ecco un primo passaggio per normalizzare la tua tabella:
-- 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;
(Non seguo il baseball, quindi potrei solo indovinare alcuni dei nomi delle colonne.) Nota che il year_id
, month_id
e day_id
le colonne sono sparite, poiché quei valori possono essere ricreati da game_date
colonna come ho indicato nei commenti. Anche il tuo game_id
la colonna è sparita; questo può essere ricreato concatenando opposing_team
, game_date
e game_seq
(che presumo sia per tenere conto delle doppie intestazioni ecc.) Ho anche convertito W
e L
in un'unica colonna destinata a contenere i valori "W" (vittoria), "L" (perdita) e "T" (pareggio).
Le teams
table fornisce una tabella di ricerca per gli ID team a 3 caratteri. Può essere ampliato per contenere tutti i dati del team che desideri. (Nota che ha lo scopo di descrivere la squadra stessa; attività del team andrebbe in un'altra tabella.)
Per rispondere alla tua domanda sulle clausole di "vincolo", la prima (CONSTRAINT starting_pitcher_log_pk
e la riga rientrata sotto di essa) specifica che la concatenazione di queste tre colonne funge da identificatore univoco primario per ciascuna riga della tabella. La seconda (CONSTRAINT team_fk FOREIGN KEY (opposing_team)
e le righe rientrate sotto di esso) significa che per un valore da inserire nel opposing_team
colonna deve già esistere nel teams.team_id
colonna; non puoi giocare contro una squadra che non esiste.
Ora lavora per rispondere effettivamente alla tua domanda originale. La migliore soluzione che ho potuto trovare su MySQL è stata una tabella scratch e una procedura memorizzata, come segue:
-- 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;
E la procedura memorizzata:
------------------------------------------------------------------------------ --
-- 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
Questa procedura cancella la tabella ip_subtotal
, lo popola dal tavolo principale, quindi arrotola il totale parziale per gli inning lanciati. Utilizza anche un semplice control-break per ripristinare l'accumulatore all'inizio dell'anno. Dopo aver eseguito la procedura eseguendo
CALL accumulate_innings();
puoi interrogare il ip_subtotal
tavolo o unisciti di nuovo al starting_pitchers_game_log
tabella come desiderato.
La procedura potrebbe anche essere estesa per accettare una data di inizio e di fine; Lo lascio come esercizio per il lettore.
Spero che sia di aiuto; è stato interessante e mi ha costretto a imparare un po' di MySQL.