sql >> Databáze >  >> RDS >> Mysql

Jak mohu přidat sloupec do pracovní tabulky pomocí nové uložené procedury

Tato otázka a její odpověď vycházejí z odpovědí na Jak mohu zkombinovat dvě procedury do jedné, aby se naplnila jedna tabulka místo toho, aby každá ze dvou procedur vyplnila svou vlastní tabulku? a Jak mohu přidat sloupec, který se zvyšuje o další sloupec ve stejné tabulce? a odpověď na tuto otázku vyžaduje drobné změny v odpovědi na předchozí dvě, které si v případě potřeby všimnu.

Vzhledem k tomu, že výpočty „doba odpočinku nad džbánem“ a „průměr získaných běhů“ jsou na sobě nezávislé, doporučuji pro každý samostatný postup. Protože však výsledky těchto dvou postupů budou často používány společně, doporučuji pro výpočty společnou stírací tabulku a navrhuji refaktorování vytvoření a naplnění této stírací tabulky do třetí procedury:

DELIMITER $$

-- DROP PROCEDURE pitcher_stats_reset $$

CREATE PROCEDURE pitcher_stats_reset()
BEGIN
  DROP TEMPORARY TABLE IF EXISTS pitcher_stats_temp;

  CREATE TEMPORARY TABLE pitcher_stats_temp
  (
    pitcher_id      char(10)    NOT NULL,
    game_date       date        NOT NULL,
    game_seq        int         NOT NULL,
    innings_pitched double      DEFAULT 0.0,
    ip_total        double      DEFAULT 0.0,
    earned_runs     INT         DEFAULT 0,
    er_total        INT         DEFAULT 0,
    std_era         DOUBLE      DEFAULT 0.0,
    starter_rest    INT         DEFAULT 0,
    CONSTRAINT pitcher_stats_temp_pk
      PRIMARY KEY (pitcher_id , game_date , game_seq )
  ) ENGINE=InnoDB;

  INSERT INTO pitcher_stats_temp
        (pitcher_id, game_date, game_seq, innings_pitched, earned_runs)
      SELECT pitcher_id, game_date, game_seq,
          IFNULL(innings_pitched, 0),  -- replace NULL with 0, if
          IFNULL(runs, 0)              --   column not initialized
        FROM starting_pitchers_game_log;
END $$

DELIMITER ;

Předchozí verze používala normální trvalou tabulku, protože jsem ještě nebyl obeznámen s tím, jak MySQL zachází s dočasnými tabulkami. Dočasná tabulka je automaticky zrušena, když se uživatel odhlásí, čímž se získá zpět místo použité pro odvozená data, která lze v případě potřeby znovu obnovit. Vypuštění a opětovné vytvoření tabulky je ekvivalentní TRUNCATE ing (kromě toho, že tabulka nemusí existovat předem), což je zase mnohem rychlejší než bezpodmínečné DELETE , podle dokumentů MySQL. Provedl jsem příslušné anotované změny v vydělaný-běh-průměrný postup také.

Postup výpočtu doby odpočinku nadhazovačů se opět řídí standardním idiomem „kontrola-přestávka“. Všimněte si, že před vstupem do smyčky jednou načteme první záznam a nastavíme ovládací pole, poté v rámci smyčky otestujeme naši výstupní podmínku, zpracujeme „aktuální“ záznam, přečteme „další“ záznam a smyčku.

DROP PROCEDURE IF EXISTS pitcher_stats_rest_time;

DELIMITER $$

CREATE PROCEDURE pitcher_stats_rest_time()
  BEGIN
    DECLARE pit_id          CHAR(10);
    DECLARE prev_pit        CHAR(10);
    DECLARE gdate           DATE;
    DECLARE seq             INT;
    DECLARE prev_date       DATE;
    DECLARE rest_days       INT;
    DECLARE end_of_cursor   BOOLEAN;

    DECLARE no_table CONDITION FOR SQLSTATE '42S02';

    DECLARE c1 CURSOR FOR
      SELECT pitcher_id, game_date, game_seq
        FROM pitcher_stats_temp
        ORDER BY pitcher_id, game_date, game_seq;

    DECLARE CONTINUE HANDLER FOR NOT FOUND
      SET end_of_cursor := TRUE;

    DECLARE EXIT HANDLER FOR no_table
    BEGIN
      SIGNAL no_table
        SET MESSAGE_TEXT = "Work table not initialized. Please call pitcher_stats_reset() before continuing",
        MYSQL_ERRNO = 1146;
    END;

    SET end_of_cursor := FALSE;

    -- Read first record and initialize control fields
    OPEN c1;
    FETCH c1 INTO pit_id, gdate, seq;
    SET prev_date := 0;
    SET prev_pit := pit_id;

    fetch_loop: LOOP
      -- Test for end-of-cursor
      IF end_of_cursor THEN
        LEAVE fetch_loop;
      END IF;

      -- Test for change in control fields. If the pitcher changes,
      --  fake a change in the year to trigger the break.
      IF pit_id != prev_pit THEN
        SET prev_date := 0;
      END IF;

      IF YEAR(prev_date) = YEAR(gdate) THEN
        SET rest_days := DATEDIFF(gdate, prev_date);
      ELSE
        SET rest_days := 0;
      END IF;

      UPDATE pitcher_stats_temp
        SET starter_rest = rest_days
        WHERE pitcher_id = pit_id
          AND game_date = gdate
          AND game_seq = seq;

      -- After processing record, update control fields
      SET prev_date := gdate;
      SET prev_pit := pit_id;

      -- Read next record and repeat
      FETCH c1 INTO pit_id, gdate, seq;
    END LOOP;

    CLOSE c1;

  END $$

DELIMITER ;

Používá se pitcher_stats_reset() se zavolá jako první, aby se inicializovala pracovní tabulka. Jakmile to uděláte, pitcher_stats_era() a pitcher_stats_rest_time() lze volat opakovaně v libovolném pořadí. Pokud pitcher_stats_reset() není voláno jako první, ostatní dva postupy vydají zdvořilou připomínku, aby tak učinily.




  1. Nelze se připojit k postgresovému serveru v dockeru z dockerizované aplikace

  2. Vytvořte funkci s volitelnými argumenty v MySQL

  3. Indexy SQL Server – vzestupné nebo sestupné, jaký je v tom rozdíl?

  4. MySQL:není ve skupině GROUP BY