Mysql
 sql >> база данни >  >> RDS >> Mysql

Как мога да добавя колона, която се увеличава в друга колона в същата таблица?

Най-добрият ми съвет към вас е, не правете това. Съхраняването на информация, която може да бъде извлечена от друга информация в базата данни, обикновено се счита за много лош дизайн и опитът да се разчита на реда на редовете в базата данни е сигурен път към лудостта.

Ето един първи път за нормализиране на вашата таблица:

-- 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 (което предполагам, че отчита двойните заглавки и др.) Преобразувах също W и L в една колона, предназначена да съдържа стойностите „W“ (победа), „L“ (загуба) и „T“ (равенство).

teams таблицата предоставя справочна таблица за 3-знаковите идентификатори на екипа. Може да се разшири, за да съдържа всякакви други данни за екипа, които искате. (Обърнете внимание, че има за цел да опише самия отбор; екипни дейности ще отиде на друга маса.)

За да отговорите на въпроса ви относно клаузите "ограничение", първата (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.




  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 параметризирана заявка в ASP.NET

  2. Реализация на MySQL с CUDA

  3. Предупреждение:mysql_fetch_array() очаква параметър 1 да бъде ресурс [...]

  4. Преобразувайте strftime в SQLite заявка в MySQL

  5. Попълване на JTree от база данни