sql >> Database teknologi >  >> RDS >> Mysql

Hvordan kan jeg tilføje en kolonne, der stiger på en anden kolonne i samme tabel?

Mit bedste råd til dig er, lad være med at gøre dette. Lagring af information, der kan udledes af andre oplysninger i databasen, anses generelt for at være meget dårligt design, og forsøg på at stole på rækkefølgen af ​​rækkerne i databasen er en sikker vej til vanvid.

Her er et første skridt til at normalisere dit bord:

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

(Jeg følger ikke baseball, så jeg kunne kun gætte på nogle af kolonnenavnene.) Bemærk at year_id , month_id og day_id kolonner er væk, da disse værdier kan genskabes fra game_date kolonne, som jeg angav i kommentarerne. Også dit game_id kolonne er væk; dette kan genskabes ved at sammenkæde opposing_team , game_date og game_seq (hvilket jeg formoder er at tage højde for dobbelt-headers osv.) Jeg har også konverteret W og L i en enkelt kolonne beregnet til at indeholde værdierne "W" (vinde), "L" (tab) og "T" (uafgjort).

teams tabel giver en opslagstabel for 3-char team-id'erne. Det kan udvides til at indeholde alle andre teamdata, du ønsker. (Bemærk, at det er beregnet til at beskrive holdet selve; team aktiviteter ville gå i en anden tabel.)

For at besvare dit spørgsmål om "constraint"-sætningerne, den første (CONSTRAINT starting_pitcher_log_pk og den indrykkede linje under den) angiver, at sammenkædningen af ​​disse tre kolonner fungerer som den primære unikke identifikator for hver række i tabellen. Den anden (CONSTRAINT team_fk FOREIGN KEY (opposing_team) og de indrykkede linjer under det) betyder, at for en værdi, der skal placeres i opposing_team kolonne, den skal allerede eksistere i teams.team_id kolonne; du kan ikke spille mod et hold, der ikke eksisterer.

Nu skal du arbejde på rent faktisk at besvare dit oprindelige spørgsmål. Den bedste løsning, jeg kunne finde på på MySQL, var en scratch-tabel og en lagret procedure, som følger:

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

Og den lagrede procedure:

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

Denne procedure rydder tabellen ip_subtotal , udfylder det fra hovedtabellen, og opruller derefter den løbende total for innings pitched. Den bruger også en simpel kontrol-pause til at nulstille akkumulatoren i starten af ​​året. Når du har kørt proceduren ved at udføre

CALL accumulate_innings();
 

du kan forespørge på ip_subtotal bordet eller slutte sig til det tilbage til starting_pitchers_game_log bord som ønsket.

Proceduren kunne også udvides til at acceptere en start- og slutdato; Det efterlader jeg som en øvelse til læseren.

Håber dette hjælper; det var interessant og tvang mig til at lære lidt MySQL.




  1. MySQL:ugedatointerval fra ugenummer i en forespørgsel

  2. TypeError:Kan ikke læse egenskaben 'adgangskode' for udefineret i login-ruten

  3. Mysql strip tidskomponent fra datetime

  4. Hvad er forskellen mellem char, nchar, varchar og nvarchar i SQL Server?