Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak dodać kolumnę, która zwiększa się w innej kolumnie w tej samej tabeli?

Moja najlepsza rada dla ciebie to:nie rób tego. Przechowywanie informacji, które można uzyskać z innych informacji w bazie danych, jest ogólnie uważane za bardzo kiepski projekt i próba polegania na kolejności wierszy w bazie danych to pewna droga do szaleństwa.

Oto pierwszy krok w normalizacji stołu:

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

(Nie śledzę baseballu, więc mogłem tylko zgadywać nazwy niektórych kolumn.) Zauważ, że year_id , month_id i day_id kolumny zniknęły, ponieważ te wartości można odtworzyć z game_date kolumna jak wskazałem w komentarzach. Również Twój game_id kolumna zniknęła; można to odtworzyć, łącząc opposing_team , game_date i game_seq (przypuszczam, że uwzględnia podwójne nagłówki itp.) Przekonwertowałem również W i L w jedną kolumnę przeznaczoną do przechowywania wartości „W” (wygrana), „L” (strata) i „T” (remis).

teams table udostępnia tabelę przeglądową dla 3-znakowych identyfikatorów zespołów. Można go rozszerzyć, aby przechowywać dowolne inne dane zespołu. (Pamiętaj, że ma to na celu opisanie samego zespołu; działania zespołu poszedłby do innego stolika.)

Aby odpowiedzieć na Twoje pytanie dotyczące klauzul „ograniczenia”, pierwsza z nich (CONSTRAINT starting_pitcher_log_pk i wcięty wiersz poniżej) określa, że ​​połączenie tych trzech kolumn służy jako podstawowy unikalny identyfikator dla każdego wiersza w tabeli. Drugi (CONSTRAINT team_fk FOREIGN KEY (opposing_team) a wcięte linie pod nim) oznaczają, że wartość ma być umieszczona w opposing_team kolumna musi już istnieć w teams.team_id kolumna; nie możesz grać przeciwko drużynie, która nie istnieje.

Teraz popracuj nad odpowiedzią na Twoje pierwotne pytanie. Najlepszym rozwiązaniem, jakie udało mi się wymyślić w MySQL, była tabela zdrapek i procedura składowana w następujący sposób:

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

A procedura składowana:

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

Ta procedura czyści tabelę ip_subtotal , wypełnia ją z głównego stołu, a następnie podlicza sumę bieżącą dla rozrzuconych inningów. Wykorzystuje również prostą przerwę kontrolną, aby zresetować akumulator na początku roku. Po uruchomieniu procedury przez wykonanie

CALL accumulate_innings();

możesz zapytać o ip_subtotal lub dołącz do niego z powrotem do starting_pitchers_game_log tabela według potrzeb.

Procedurę można by również rozszerzyć, aby zaakceptować datę rozpoczęcia i zakończenia; Zostawiam to jako ćwiczenie dla czytelnika.

Mam nadzieję że to pomoże; to było interesujące i zmusiło mnie do nauczenia się trochę 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 Stored Procedure, Zapytanie, aby sprawdzić, czy istnieje, czy nie

  2. SQL:wydajność łączenia w łańcuchy

  3. Jak ukryć ciąg połączenia MySQL — nazwa użytkownika i hasło w serwisie GitHub (Java)

  4. Uzyskiwanie dokładnej różnicy czasu z pola datetime MYSQL

  5. MySQL:grupowanie według daty ZAKRES?