草庐IT

mysql - 访问同一查询中先前更新的列的行为与 JOIN/多表 UPDATE 不同

coder 2023-10-12 原文

假设我有两个表 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 计数器,同时更新他们的赢/输比。这看起来像这样:

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

请注意,win 的增量值用于计算ratio(正如mysql 的手册在这里指出:1.8.2.2 UPDATE Differences)。

现在,当将 JOIN 添加到 UPDATE 查询以将其限制为仅更新 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 会这样,是否有更优雅的解决方案来解决此类问题(除了创建一个 View 来动态计算比率)?

表创建如下:

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

最佳答案

我无法解释确实看起来很奇怪的 join case 的行为,但以下工作按预期进行:

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

关于mysql - 访问同一查询中先前更新的列的行为与 JOIN/多表 UPDATE 不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42740257/

有关mysql - 访问同一查询中先前更新的列的行为与 JOIN/多表 UPDATE 不同的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  6. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  7. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  8. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  9. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  10. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

随机推荐