Moja najlepsza rada dla ciebie to:nie rób tego. Przechowywanie informacji, które można uzyskać z innych informacji w bazie danych, jest ogólnie uważane za bardzo kiepski projekt i próba polegania na kolejności wierszy w bazie danych to pewna droga do szaleństwa.
Oto pierwszy krok w normalizacji stołu:
-- 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;
(Nie śledzę baseballu, więc mogłem tylko zgadywać nazwy niektórych kolumn.) Zauważ, że year_id
, month_id
i day_id
kolumny zniknęły, ponieważ te wartości można odtworzyć z game_date
kolumna jak wskazałem w komentarzach. Również Twój game_id
kolumna zniknęła; można to odtworzyć, łącząc opposing_team
, game_date
i game_seq
(przypuszczam, że uwzględnia podwójne nagłówki itp.) Przekonwertowałem również W
i L
w jedną kolumnę przeznaczoną do przechowywania wartości „W” (wygrana), „L” (strata) i „T” (remis).
teams
table udostępnia tabelę przeglądową dla 3-znakowych identyfikatorów zespołów. Można go rozszerzyć, aby przechowywać dowolne inne dane zespołu. (Pamiętaj, że ma to na celu opisanie samego zespołu; działania zespołu poszedłby do innego stolika.)
Aby odpowiedzieć na Twoje pytanie dotyczące klauzul „ograniczenia”, pierwsza z nich (CONSTRAINT starting_pitcher_log_pk
i wcięty wiersz poniżej) określa, że połączenie tych trzech kolumn służy jako podstawowy unikalny identyfikator dla każdego wiersza w tabeli. Drugi (CONSTRAINT team_fk FOREIGN KEY (opposing_team)
a wcięte linie pod nim) oznaczają, że wartość ma być umieszczona w opposing_team
kolumna musi już istnieć w teams.team_id
kolumna; nie możesz grać przeciwko drużynie, która nie istnieje.
Teraz popracuj nad odpowiedzią na Twoje pierwotne pytanie. Najlepszym rozwiązaniem, jakie udało mi się wymyślić w MySQL, była tabela zdrapek i procedura składowana w następujący sposób:
-- 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;
A procedura składowana:
------------------------------------------------------------------------------ --
-- 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
Ta procedura czyści tabelę ip_subtotal
, wypełnia ją z głównego stołu, a następnie podlicza sumę bieżącą dla rozrzuconych inningów. Wykorzystuje również prostą przerwę kontrolną, aby zresetować akumulator na początku roku. Po uruchomieniu procedury przez wykonanie
CALL accumulate_innings();
możesz zapytać o ip_subtotal
lub dołącz do niego z powrotem do starting_pitchers_game_log
tabela według potrzeb.
Procedurę można by również rozszerzyć, aby zaakceptować datę rozpoczęcia i zakończenia; Zostawiam to jako ćwiczenie dla czytelnika.
Mam nadzieję że to pomoże; to było interesujące i zmusiło mnie do nauczenia się trochę MySQL.