我有一个名为“IP”的列表,我想在同一个表“YTD_IP”中创建另一个列,它将给出“IP”(投票局)的累计年初至今的总和一年中任何给定的游戏,反映在同一季节之前的游戏(行/事件)投放的总和。一旦年度发生变化,我希望总和再次从0开始。
以下是“PIT_ID”,“YEAR_ID”,“IP”列的数据示例,以及我希望看到“YTD_IP”列的内容:
Pit_ID YEAR_ID IP YTD_IP
aased001 1977 9.0000 9
aased001 1977 9.0000 18
aased001 1977 7.0000 25
aased001 1977 5.0000 30
aased001 1977 6.3333 36.3333
aased001 1977 6.3333 42.6666
aased001 1977 7.0000 49.6666
aased001 1977 6.0000 55.6666
aased001 1977 9.0000 64.6666
aased001 1977 9.0000 73.6666
aased001 1977 5.0000 78.6666
aased001 1977 6.3333 84.9999
aased001 1977 7.3333 92.3333
aased001 1978 4.3333 4.3333
aased001 1978 7.0000 11.3333
aased001 1978 6.3333 17.6666
aased001 1978 3.3333 20.9999
我把以下代码放在一起:
ALTER TABLE starting_pitcher_game_log ADD COLUMN YTD_IP VARCHAR(255);
SET YTD_IP:= 0;
SELECT a.IP, b.YEAR_ID
IF(@prevYEAR_ID != YEAR_ID,IP,@YTD_IP+IP) AS IP,
@prevYEAR_ID=YEAR_ID
FROM starting_pitcher_game_log
但它不正确,因为它收到以下错误:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF(@prevYEAR_ID != YEAR_ID,IP,@YTD_IP+IP) AS IP,
@prevYEAR_ID=YEAR_ID
' at line 2
有没有办法确保它适应未来将要播放的游戏?
任何帮助都会有很长的路要走。
嗨达尔文,
您可以共享可用于临时调用列的代码以及可能创建累积和字段的永久代码吗?特别是,我想在一个名为“YTD_IP”的表格中创建另一个专栏,该专栏将给出从赛季开始到该赛季任何特定比赛的“IP”(投球局)累计年初至今的总和反映在给定游戏之前的游戏(行/事件)中给定投手投球的总和+在该游戏中投入的局数。一旦季节发生变化,我希望总和再次从0开始。
感谢您的帮助。
答案 0 :(得分:1)
我最好的建议是,不要这样做。存储可以从数据库中的其他信息导出的信息通常被认为是非常糟糕的设计,并且试图依赖于数据库中的行的顺序是疯狂的可靠途径。
这是规范化你的桌子的第一步:
-- 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
列重新创建值。您的game_id
列也已消失;这可以通过连接opposing_team
,game_date
和game_seq
来重新创建(我认为这是为了说明双标题& c。)我还转换了W
和L
到一个列中,用于保存值“W”(胜利),“L”(亏损)和“T”(平局)。
teams
表提供了3-char团队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。