Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana saya bisa menambahkan kolom yang bertambah pada kolom lain di tabel yang sama?

Saran terbaik saya untuk Anda adalah, Jangan lakukan ini. Menyimpan informasi yang dapat diturunkan dari informasi lain dalam database umumnya dianggap desain yang sangat buruk, dan berusaha mengandalkan urutan baris dalam database adalah jalan pasti menuju kegilaan.

Inilah cara pertama untuk menormalkan tabel Anda:

-- 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;

(Saya tidak mengikuti bisbol, jadi saya hanya bisa menebak beberapa nama kolom.) Perhatikan bahwa year_id , month_id dan day_id kolom hilang, karena nilai tersebut dapat dibuat kembali dari game_date kolom seperti yang saya tunjukkan di komentar. Juga game_id . Anda kolom hilang; ini dapat dibuat ulang dari menggabungkan opposing_team , game_date dan game_seq (yang saya kira adalah untuk memperhitungkan tajuk ganda &c.) Saya juga telah mengonversi W dan L menjadi satu kolom yang dimaksudkan untuk menampung nilai "W" (menang), "L" (kalah), dan "T" (seri).

teams table menyediakan tabel pencarian untuk id tim 3-char. Itu dapat diperluas untuk menampung data tim lain yang Anda inginkan. (Perhatikan bahwa ini dimaksudkan untuk menggambarkan tim itu sendiri; tim aktivitas akan pergi ke meja lain.)

Untuk menjawab pertanyaan Anda tentang klausa "kendala", yang pertama (CONSTRAINT starting_pitcher_log_pk dan garis indentasi di bawahnya) menetapkan bahwa rangkaian ketiga kolom tersebut berfungsi sebagai pengidentifikasi unik utama untuk setiap baris dalam tabel. Yang kedua (CONSTRAINT team_fk FOREIGN KEY (opposing_team) dan garis indentasi di bawahnya) berarti bahwa untuk nilai yang akan ditempatkan di opposing_team kolom itu harus sudah ada di teams.team_id kolom; Anda tidak bisa bermain melawan tim yang tidak ada.

Sekarang untuk benar-benar menjawab pertanyaan awal Anda. Solusi terbaik yang dapat saya temukan di MySQL adalah tabel awal dan prosedur tersimpan, sebagai berikut:

-- 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;

Dan prosedur tersimpan:

------------------------------------------------------------------------------    --
-- 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

Prosedur ini menghapus tabel ip_subtotal , mengisinya dari tabel utama, lalu menggulung total lari untuk pitch inning. Ini juga menggunakan kontrol-break sederhana untuk mengatur ulang akumulator pada awal tahun. Setelah Anda menjalankan prosedur dengan menjalankan

CALL accumulate_innings();

Anda dapat menanyakan ip_subtotal tabel atau gabungkan kembali ke starting_pitchers_game_log tabel sesuai keinginan.

Prosedur juga dapat diperpanjang untuk menerima tanggal mulai dan berakhir; Saya meninggalkan itu sebagai latihan untuk pembaca.

Semoga ini membantu; itu menarik dan memaksa saya untuk belajar sedikit 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. Fungsi jendela Postgres lag() setara permintaan di MySQL

  2. Dukungan PDO untuk beberapa kueri (PDO_MYSQL, PDO_MYSQLND)

  3. Bergabunglah dengan dua tabel MySQL dengan PHP

  4. PHP 7 tidak dapat menemukan MySQLi

  5. Terhubung ke database MySQL dengan C# sebagai pengguna non-root?