【问题标题】:Rails: update multiple records single column value while the records were retrieved using a group by clauseRails:在使用 group by 子句检索记录时更新多条记录单列值
【发布时间】:2017-03-16 22:46:27
【问题描述】:

我正在使用 group by 子句从表中检索一些数据,之后我想为初始查询检索到的所有记录更新单个列值。

所以我需要确保从初始查询到我更新记录之前没有添加新行。

解释:假设模型 Test 有 5 列:Id A B C Status

所以我首先查询如下:

Test.select('count(*), A, B').where(status:'new', C: 'value').group('A, B')

在我处理完代码中的组后,我想将初始查询中 used 的所有记录的状态更改为 done

问题是,如果我只是这样做:

Test.where(status: 'new', C: 'value')

为了现在使用update_all,自第一个回答此条件的查询以来,有可能将新记录添加到表中,我会将它们的状态设置为“完成”,尽管它们并没有真正被处理,因为在初始查询它们不存在。

所以基本上我需要一种方法来锁定从初始查询到更新的插入表,或者以某种方式获取在查询组中“考虑”的 id 列表。

我该怎么做?

【问题讨论】:

    标签: ruby-on-rails ruby postgresql activerecord rails-activerecord


    【解决方案1】:

    我建议在第一个查询中也从 select 语句中选择 id。

    Test.select('count(*), A, B, Id').where(status:'new', C: 'value').group('A, B').
    

    从上述查询中选择 ID。然后使用另一个查询来更新它们。

    Test.where("Id IN ?", ids ).update_all()
    

    根据您的要求进行必要的更改。

    【讨论】:

    • 不需要遍历每个Test对象,你可以对ActiveRecord::Relation返回的Test.where()做一个update_all
    • 谢谢我的朋友。更新了答案。
    • 我不明白。将“id”添加到 group_by 不会破坏 group_by 的全部意义吗?我错过了什么吗?
    • 如果由于某种原因不清楚,则 id 是唯一的
    • 你可以不使用 ID 进行分组吗?然后您可以从组中删除 Id。由于您选择 Id,它有时可能会要求您将 Id 添加到您的组。
    【解决方案2】:

    group_by 和 update_all (Rails 7+)

    Starting from Rails 7, there is an ability to use group_by and having with update_all.

    所以现在,可以编写如下查询:

    Post.joins(:comments).group("posts.id").having("count(comments.id) >= 2").update_all
    

    生成以下 SQL (query may differ depending on DBMS):

    UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
      SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" 
      GROUP BY posts.id HAVING (count(comments.id) >= 2)
    )  [["flagged", "t"]]
    

    它在单个事务中选择和更新记录。

    来源

    【讨论】:

      猜你喜欢
      • 2020-10-15
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-03
      • 1970-01-01
      相关资源
      最近更新 更多