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 tableは、3文字のチームIDのルックアップテーブルを提供します。必要な他のチームデータを保持するように拡張できます。 (チーム自体を説明するためのものであることに注意してください。 チームアクティビティ 別のテーブルに入れます。)

    「制約」句に関する質問に答えるには、最初の句(CONSTRAINT starting_pitcher_log_pk その下のインデントされた行)は、これら3つの列の連結が、テーブルの各行の主要な一意の識別子として機能することを示しています。 2番目のもの(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. SQL Server 2017/2019のSERVERPROPERTY()からすべてのプロパティを返すクイックスクリプト

    2. Jenkins Script Console/ScriptlerのConnector/JMySQLドライバー

    3. mysqlを使用してPDOでONDUPLICATEKEY UPDATEを使用するにはどうすればよいですか?

    4. Oracleのログテーブルから電子メール本文にデータをエクスポートする方法