update_all with a method
让我们说我有一个模型:
class Result < ActiveRecord::Base attr_accessible :x, :y, :sum end
而不是做
Result.all.find_each do |s| s.sum = compute_sum(sx, sy) s.save end
假设compute_sum
是一个可用的方法,并进行一些无法转换为SQL的计算。
def compute_sum(x,y) sum_table[x][y] end
有没有办法使用update_all
,可能是这样的:
Result.all.update_all(sum: compute_sum(:x, :y))
我有超过80,000条记录需要更新。 find_each
每条记录find_each
创建自己的BEGIN
和COMMIT
查询,并且每条记录都会单独更新。
或者还有其他更快的方法吗?
如果compute_sum函数无法转换为sql,则无法一次对所有记录执行update_all。 您需要遍历各个实例。 但是,如果列中有很多重复的值集,只需对每组输入进行一次计算,然后每次计算进行一次质量更新,就可以加快速度。 例如
Result.all.group_by{|result| [result.x, result.y]}.each do |inputs, results| sum = compute_sum(*inputs) Result.update_all('sum = #{sum}', "id in (#{results.map(&:id).join(',')})") end
您可以将result.x,result.y替换为compute_sum函数的实际输入。
编辑 – 忘记在group_by块中的result.x,result.y周围放置方括号。
update_all
进行sql查询,因此对值执行的任何处理都需要在sql中。 因此,您需要在您使用的任何DBMS中找到sql函数,以将两个数字相加。 例如,在Postgres,我相信你会这样做
Sum.update_all(sum: "x + y")
这会生成这个sql:
update sums set sum = x + y;
它将计算每行的x + y值,并将sum字段设置为结果。
编辑 – 为MariaDB。 我从来没有使用过这个,但快速谷歌建议sql会
update sums set sum = sum(x + y);
首先在sql控制台中尝试使用单个记录。 如果它有效,那么你可以做到
Sum.update_all(sum: "sum(x + y)")
在Rails中。
EDIT2:这里有很多名为sum
的东西,这使得这个例子非常混乱。 这是一个更通用的例子。
将col_c设置为在类Foo中将col_a和col_b一起添加的结果:
Foo.update_all(col_c: "sum(col_a + col_b)")
我刚注意到我从你的问题中复制了(不正确的) Sum.all.update_all
。 它应该只是Sum.update_all
– 我已经更新了我的答案。
我完全是初学者,只是想知道为什么不在下面添加一个自我阻止,而不在db中添加单独的列,你仍然可以从外部访问Sum.sum。
def self.sum x+y end
- Ruby on Rails迁移,将表更改为MyISAM
- 将查找条件添加到Rails中的所有活动记录模型
- 是否可以根据单个对象对方法的响应对对象列表进行排序?
- 如何存储和比较:ActiveRecord中的符号(Ruby on Rails)
- undefined方法`default_scoped?’ 在访问范围时
- PG :: GroupingError:错误:列“events.id”必须出现在GROUP BY子句中或用于聚合函数
- 具有多个联接的ActiveRecord查询无法识别关系
- 如何测试ActiveRecord中哪些validation失败?
- 如何构建用于查询Redshift数据库的前端(希望使用Rails)