【问题标题】:How can I add a column that increments on another column in same table?如何添加在同一个表中的另一列上递增的列?
【发布时间】:2016-02-24 22:15:52
【问题描述】:

我有一个表,其中有一列名为“IP”,我想在同一个表“YTD_IP”中创建另一列,这将给出“IP”的累计年初至今总和(投球局数)一年中的任何给定比赛,反映了在同一赛季之前的比赛(行/事件)中投的局数。一旦年份发生变化,我希望总和再次从 0 开始。

这是“PIT_ID”、“YEAR_ID”、“IP”列的数据示例,以及我希望看到“YTD_IP”列的样子:

Pit_ID  YEAR_ID  IP      YTD_IP
aased001      1977  9.0000    9
aased001      1977  9.0000    18
aased001      1977  7.0000    25
aased001      1977  5.0000    30
aased001      1977  6.3333    36.3333
aased001      1977  6.3333    42.6666
aased001      1977  7.0000    49.6666
aased001      1977  6.0000    55.6666
aased001      1977  9.0000    64.6666
aased001      1977  9.0000    73.6666
aased001      1977  5.0000    78.6666
aased001      1977  6.3333    84.9999
aased001      1977  7.3333    92.3333
aased001      1978  4.3333     4.3333
aased001      1978  7.0000    11.3333
aased001      1978  6.3333    17.6666
aased001      1978  3.3333    20.9999

我整理了以下代码:

ALTER TABLE starting_pitcher_game_log ADD COLUMN YTD_IP VARCHAR(255);
    SET YTD_IP:= 0;
    SELECT a.IP,  b.YEAR_ID
      IF(@prevYEAR_ID != YEAR_ID,IP,@YTD_IP+IP) AS IP,
      @prevYEAR_ID=YEAR_ID
    FROM starting_pitcher_game_log

但这不对,因为它得到以下错误:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF(@prevYEAR_ID != YEAR_ID,IP,@YTD_IP+IP) AS IP,
          @prevYEAR_ID=YEAR_ID
' at line 2

有没有办法确保它适应未来将要玩的游戏?

任何帮助都会大有帮助。

screen shot of full table

你好,达尔文,

您能否分享适用于临时调用列的代码以及可用于创建累积和字段的永久列的代码?特别是,我想在名为“YTD_IP”的表中创建另一列,该列将给出从赛季开始到该赛季任何给定比赛的“IP”(投球局)的累计年初至今总和反映给定投手在给定比赛之前的比赛(行/事件)中投的局数 + 在该比赛中投的局数。一旦季节发生变化,我希望总和再次从 0 开始。

感谢您的帮助。

【问题讨论】:

    标签: mysql increment


    【解决方案1】:

    我对你最好的建议是,不要这样做。在数据库中存储可以从其他信息中获得的信息通常被认为是非常糟糕的设计,并且试图依赖于数据库中行的顺序肯定会导致疯狂。

    这是规范化表格的第一步:

    -- 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_idmonth_idday_id 列已经消失,因为这些值可以从game_date 列,正如我在 cmets 中指出的那样。你的game_id 栏也不见了;这可以通过连接 opposing_teamgame_dategame_seq 重新创建(我认为这是为了考虑双标题等。)我还将 WL 转换为一个旨在容纳的单列值“W”(赢)、“L”(输)和“T”(平)。

    teams 表为 3 字符团队 ID 提供了一个查找表。它可以扩展以保存您想要的任何其他团队数据。 (注意这是为了描述团队本身;团队活动会放在另一个表中。)

    要回答您关于“约束”子句的问题,第一个子句(CONSTRAINT starting_pitcher_log_pk 及其下方的缩进行)指定这三列的串联用作表中每一行的主要唯一标识符。第二个(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。

    【讨论】:

    • 感谢您分享您的谨慎想法。你能澄清一下你所说的一些事情吗?我不确定它是否有区别,但 PIT_ID 列是从同一个表中的另一列派生的,这与我称为 GAME_ID 的另一个表中的列相同。因此,每个 PIT_ID 条目/值都与一个特定的 GAME_ID 文件绑定,该文件指定了比赛的日期和他所对阵的球队——这部分使得我试图创建的列中的值不会仅依赖于当前的排序顺序,但依赖于随之而来的 yoked GAME_ID 文件。
    • 为了澄清,我的意思是说每个 PIT_ID 值都与同一个表中另一个名为“GAME_ID”的列中的唯一值(日期)挂钩。
    • 您能发布此表的完整布局吗?
    • 我在底部的主帖中添加了指向表格屏幕截图的链接。感谢您的帮助。
    • 您会反对对该表进行大修和规范化吗?我看到了很多优化空间,可以简化、缩小它,并避免保持多列相互一致的工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多