Mijn beste advies aan jou is:doe dit niet. Het opslaan van informatie die kan worden afgeleid uit andere informatie in de database wordt over het algemeen als een zeer slecht ontwerp beschouwd en proberen te vertrouwen op de volgorde van de rijen in de database is een zeker pad naar waanzin.
Hier is een eerste poging om uw tafel te normaliseren:
-- 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;
(Ik volg honkbal niet, dus ik kon alleen maar raden naar enkele kolomnamen.) Merk op dat de year_id
, month_id
en day_id
kolommen zijn verdwenen, omdat die waarden opnieuw kunnen worden gemaakt vanaf de game_date
kolom zoals ik heb aangegeven in de opmerkingen. Ook je game_id
kolom is verdwenen; dit kan opnieuw worden gemaakt door opposing_team
aan elkaar te koppelen , game_date
en game_seq
(waarvan ik aanneem dat het rekening houdt met dubbele headers &c.) Ik heb ook W
geconverteerd en L
in een enkele kolom die bedoeld is om de waarden "W" (winst), "L" (verlies) en "T" (gelijkspel) te bevatten.
De teams
tabel biedt een opzoektabel voor de team-ID's van 3 tekens. Het kan worden uitgebreid om andere teamgegevens op te slaan die u wilt. (Let op:het is bedoeld om het team zelf te beschrijven; team activiteiten zou in een andere tafel gaan.)
Om uw vraag over de "beperkingsclausules" te beantwoorden, de eerste (CONSTRAINT starting_pitcher_log_pk
en de ingesprongen regel eronder) geeft aan dat de aaneenschakeling van die drie kolommen dient als de primaire unieke identificatie voor elke rij in de tabel. De tweede (CONSTRAINT team_fk FOREIGN KEY (opposing_team)
en de ingesprongen regels eronder) betekent dat voor een waarde die moet worden geplaatst in het opposing_team
kolom het moet al bestaan in de teams.team_id
kolom; je kunt niet spelen tegen een team dat niet bestaat.
Nu werken aan het daadwerkelijk beantwoorden van uw oorspronkelijke vraag. De beste oplossing die ik kon bedenken op MySQL was een kladtabel en een opgeslagen procedure, als volgt:
-- 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;
En de opgeslagen procedure:
------------------------------------------------------------------------------ --
-- 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
Deze procedure wist de tabel ip_subtotal
, vult het in vanaf de hoofdtafel en rolt vervolgens het lopende totaal op voor de gegooide innings. Het gebruikt ook een eenvoudige bedieningsonderbreking om de accu aan het begin van het jaar te resetten. Nadat u de procedure heeft uitgevoerd door
CALL accumulate_innings();
u kunt de ip_subtotal
. opvragen tafel of voeg het toe terug naar de starting_pitchers_game_log
tafel naar wens.
De procedure zou ook kunnen worden uitgebreid om een start- en einddatum te accepteren; Ik laat dat als een oefening voor de lezer.
Ik hoop dat dit helpt; het was interessant en dwong me om een beetje MySQL te leren.