说我有两个表players
和stats
,其中包括以下内容:
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);