与Join / Multi-Table更新相同的相同查询中先前更新的列的行为不同



说我有两个表playersstats,其中包括以下内容:

mysql> select * from players;
+----+-------+
| id | alive |
+----+-------+
|  1 |     0 |
|  2 |     1 |
+----+-------+
mysql> select * from stats;
+--------+------+------+-------+
| player | win  | lose | ratio |
+--------+------+------+-------+
|      1 |   12 |   20 |   0.6 |
|      2 |    8 |    1 |     8 |
+--------+------+------+-------+

我想增加每个玩家的win -counter,同时还更新他们的胜利/损失比例。看起来像这样:

update `stats` set `win` = `win` + 1, `ratio` = `win` / `lose`;

请注意,win的增量值用于计算ratio(就像MySQL的手动状态一样:1.8.2.2更新差异)。

现在,当将加入添加到Update-Query中以将其限制为仅更新alive = 1的播放器时,此行为会发生变化:

update `stats` st
inner join `players` pl
    on ( pl.`id` = st.`player` )
set `win` = `win` + 1, `ratio` = `win` / `lose`
where pl.`alive` = 1;
mysql> select * from stats;
+--------+------+------+-------+
| player | win  | lose | ratio |
+--------+------+------+-------+
|      1 |   12 |   20 |   0.6 |
|      2 |    9 |    1 |     8 |
+--------+------+------+-------+

我发现的唯一解决方案是将win的新值分配给临时变量,并在计算ratio时使用该值:

update `stats` st
inner join `players` pl
    on ( pl.`id` = st.`player` )
set
    `win` = @tmpWin := ( `win` + 1 ),
    `ratio` = @tmpWin / `lose`
where pl.`alive` = 1;

为什么MySQL会这样行事,并且对这种问题有更优雅的解决方案(创建一个视图以计算即时计算比率)?

桌子的创建如下:

create table `players` (
    `id`        INT,
    `alive`     TINYINT,
    primary key (`id`)
);
create table `stats` (
    `player`    INT,
    `win`       INT,
    `lose`      INT,
    `ratio`     FLOAT,
    primary key (`player`)
);

我正在使用mysql v5.7.17

我无法解释加入案例的行为,该行为看起来确实很奇怪,但如下所预期的是:

 UPDATE `stats` 
 SET `win` = `win` + 1, `ratio` = `win` / `lose` 
 WHERE player IN (SELECT id FROM players WHERE alive=1);

相关内容

  • 没有找到相关文章

最新更新