Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để thêm một cột tăng dần trên một cột khác trong cùng một bảng?

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_idday_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_dategame_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 WL 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.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySQL:Chọn tất cả các ngày trong một phạm vi ngay cả khi không có hồ sơ nào

  2. Lỗi khi chèn ngày - Giá trị ngày không chính xác:

  3. LỖI:Lỗi 1005:Không thể tạo bảng 'cat10e.recording' (errno:150)

  4. MySQL:sử dụng lại tự động tăng trong khi chèn

  5. SQL:Làm thế nào chúng ta có thể tạo một table1 THAM GIA table2 TRÊN một bảng được cho trong một trường trong table1?