ruby Rails:使用group by子句检索记录时更新多个记录的单个列值

kx7yvsdv  于 2023-11-18  发布在  Ruby
关注(0)|答案(2)|浏览(128)

我正在使用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列表。
我该怎么做?

eqqqjvef

eqqqjvef1#

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

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

字符串
从上面的查询中选择id。然后使用另一个查询来更新它们。

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


更新您需要的必要更改。

rm5edbpk

rm5edbpk2#

group_by和具有更新所有(Rails 7+)

Starting from Rails 7, you can 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"]]


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

来源

相关问题