sql >> データベース >  >> RDS >> Mysql

新しいストアドプロシージャを使用して作業テーブルに列を追加するにはどうすればよいですか

    この質問とその回答は、 2つのプロシージャのそれぞれが独自のテーブルにデータを入力するのではなく、2つのプロシージャを1つに組み合わせて1つのテーブルにデータを入力するにはどうすればよいですか? および同じテーブルの別の列で増分する列を追加するにはどうすればよいですか? 、そしてこの質問への回答は、前の2つの回答への小さな変更を必要とします。これについては、必要に応じて注意します。

    「ピッチャー休憩時間」と「防御率」の計算は独立しているので、それぞれ別の手順をお勧めします。ただし、2つの手順の結果は一緒に使用されることが多いため、計算には一般的なスクラッチテーブルをお勧めし、リファクタリング そのスクラッチテーブルの作成と作成を3番目の手順に:

    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 ;
    

    以前のバージョンでは、MySQLによる一時テーブルの処理にまだ慣れていなかったため、通常の永続テーブルを使用していました。ユーザーがログオフすると、一時テーブルが自動的に削除され、必要に応じて再生成できる派生データに使用されたスペースが再利用されます。テーブルを削除して再作成することは、TRUNCATEと同等です。 ing(テーブルが事前に存在する必要がないことを除く)は、無条件のDELETEよりもはるかに高速です。 、MySQLドキュメントによると。 防御率 同様に。

    ピッチャーの休憩時間を計算する手順は、再び標準の「コントロールブレイク」イディオムに従います。ループに入る前に最初のレコードを読み取り、制御フィールドを1回設定してから、ループ内で終了条件をテストし、「現在の」レコードを処理し、「次の」レコードを読み取ってループすることに注意してください。

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

    使用中、pitcher_stats_reset() 作業テーブルを初期化するために、最初に呼び出されます。それが完了したら、pitcher_stats_era() およびpitcher_stats_rest_time() 任意の順序で繰り返し呼び出すことができます。 pitcher_stats_reset()の場合 が最初に呼び出されない場合、他の2つの手順は、そうするように丁寧なリマインダーを発行します。




    1. Oracleディクショナリ・ビューを使用してPL/SQLパッケージレベルのタイプを検出

    2. MySQL-存在する場合は更新、そうでない場合は2つのキーで挿入

    3. 結果セットの最後の行のすべての列値の合計と行の合計(group by)を取得するSQLクエリ

    4. 複数のJOINSとGROUPBYCLAUSEを使用したクエリでCOUNT