我对你最好的建议是,不要这样做。在数据库中存储可以从其他信息中获得的信息通常被认为是非常糟糕的设计,并且试图依赖于数据库中行的顺序肯定会导致疯狂。
这是规范化表格的第一步:
-- 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 列,正如我在 cmets 中指出的那样。你的game_id 栏也不见了;这可以通过连接 opposing_team、game_date 和 game_seq 重新创建(我认为这是为了考虑双标题等。)我还将 W 和 L 转换为一个旨在容纳的单列值“W”(赢)、“L”(输)和“T”(平)。
teams 表为 3 字符团队 ID 提供了一个查找表。它可以扩展以保存您想要的任何其他团队数据。 (注意这是为了描述团队本身;团队活动会放在另一个表中。)
要回答您关于“约束”子句的问题,第一个子句(CONSTRAINT starting_pitcher_log_pk 及其下方的缩进行)指定这三列的串联用作表中每一行的主要唯一标识符。第二个(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。