Lời khuyên tốt nhất của tôi dành cho bạn là, Đừng làm điều này. Lưu trữ thông tin có thể bắt nguồn từ thông tin khác trong cơ sở dữ liệu thường được coi là thiết kế rất kém và cố gắng dựa vào thứ tự của các hàng trong cơ sở dữ liệu là một con đường chắc chắn dẫn đến sự điên rồ.
Đây là bước đầu tiên khi chuẩn hóa bảng của bạn:
-- 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;
(Tôi không theo dõi bóng chày, vì vậy tôi chỉ có thể đoán được một số tên cột.) Lưu ý rằng year_id
, month_id
và day_id
cột biến mất vì những giá trị đó có thể được tạo lại từ game_date
như tôi đã chỉ ra trong các bình luận. Cũng là game_id
của bạn cột đã biến mất; điều này có thể được tạo lại từ việc nối opposing_team
, game_date
và game_seq
(mà tôi cho là để giải thích cho các tiêu đề kép &c.) Tôi cũng đã chuyển đổi W
và L
vào một cột duy nhất nhằm giữ các giá trị "W" (thắng), "L" (thua) và "T" (hòa).
Các nhóm teams
bảng cung cấp một bảng tra cứu id nhóm 3 ký tự. Nó có thể được mở rộng để chứa bất kỳ dữ liệu nhóm nào khác mà bạn muốn. (Lưu ý rằng nó được dùng để mô tả chính đội; nhóm hoạt động sẽ chuyển sang một bảng khác.)
Để trả lời câu hỏi của bạn về các điều khoản "ràng buộc", điều đầu tiên (CONSTRAINT starting_pitcher_log_pk
và dòng thụt lề bên dưới) chỉ định rằng nối ba cột đó đóng vai trò là mã định danh duy nhất chính cho mỗi hàng trong bảng. Cái thứ hai (CONSTRAINT team_fk FOREIGN KEY (opposing_team)
và các dòng thụt lề bên dưới nó) có nghĩa là để một giá trị được đặt trong opposing_team
cột nó phải đã tồn tại trong teams.team_id
cột; bạn không thể đấu với một đội không tồn tại.
Bây giờ để thực sự trả lời câu hỏi ban đầu của bạn. Giải pháp tốt nhất mà tôi có thể đưa ra trên MySQL là một bảng nháp và một thủ tục được lưu trữ, như sau:
-- 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;
Và thủ tục được lưu trữ:
------------------------------------------------------------------------------ --
-- 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
Quy trình này xóa bảng ip_subtotal
, điền nó từ bảng chính, sau đó cuộn lên tổng số đang chạy cho các lượt chơi được ném. Nó cũng sử dụng một ngắt điều khiển đơn giản để đặt lại bộ tích lũy vào đầu năm. Sau khi bạn đã chạy thủ tục bằng cách thực thi
CALL accumulate_innings();
bạn có thể truy vấn ip_subtotal
hoặc tham gia nó trở lại starting_pitchers_game_log
bảng như mong muốn.
Thủ tục cũng có thể được mở rộng để chấp nhận ngày bắt đầu và ngày kết thúc; Tôi để đó như một bài tập cho người đọc.
Hi vọng điêu nay co ich; điều đó thật thú vị và buộc tôi phải học một chút MySQL.