Sql 使用独立值更新多个记录的有效方法?

Sql 使用独立值更新多个记录的有效方法?,sql,ruby-on-rails-3,rails-activerecord,Sql,Ruby On Rails 3,Rails Activerecord,我有以下(过于昂贵的)方法: 但这会导致对每个区域路径进行更新查询。有没有一种方法可以在一个查询中实现这一点 --编辑-- 根据coreyward建议,最终解决方案: def reorder_area_routes_by_demographics! sorted_ids = area_routes.joins(:route).order(self.demo_criteria, :proximity_rank).pluck(:'area_routes.id') AreaRoute.upda

我有以下(过于昂贵的)方法:

但这会导致对每个区域路径进行更新查询。有没有一种方法可以在一个查询中实现这一点

--编辑--

根据coreyward建议,最终解决方案:

def reorder_area_routes_by_demographics!
  sorted_ids = area_routes.joins(:route).order(self.demo_criteria, :proximity_rank).pluck(:'area_routes.id')
  AreaRoute.update_all [efficient_sort_sql(sorted_ids), *sorted_ids], {id: sorted_ids}
end

def efficient_sort_sql(sorted_ids, offset=0)
  offset.upto(offset + sorted_ids.count - 1).inject('match_rank = CASE id ') do |sql, i|
    sql << "WHEN ? THEN #{id} "
  end << 'END'
end
def按人口统计数据重新排列区域路线!
排序的\u id=区域\u路由。连接(:路由)。顺序(self.demo\u标准,:接近度\u排名)。清除(:'area\u路由.id'))
AreaRoute.update_all[高效排序sql(排序的id),*排序的id],{id:sorted的id}
结束
def高效排序sql(已排序的ID,偏移量=0)
offset.upto(offset+sorted_id.count-1).inject('match_rank=CASE id')do | sql,i|

sql我使用以下方法来完成类似的任务:根据一组记录在参数中的顺序更新它们的排序位置。您可能需要以不同的方式重构或合并它,以适应您正在应用的范围,但我认为这将使您朝着正确的方向前进

def efficient_sort_sql(sortable_ids, offset = 1)
  offset.upto(offset + sortable_ids.count - 1).reduce('position = CASE id ') do |sql, i|
    sql << "WHEN ? THEN #{i} "
  end << 'END'
end

Model.update_all [efficient_sort_sql(sortable_ids, offset), *sortable_ids], { id: sortable_ids }

这是一个性能相当好的查询(至少在Postgresql中)要么完全成功,要么完全失败

如果更新表时使用的新数据在数据库中,则可以在数据库上运行查询,以在一个事务中更新
区域路径中的所有值。它将比逐个更新行更快。我不熟悉Ruby,所以如果你能将语句翻译成SQL或告诉逻辑,那么我就可以编写SQL。
def efficient_sort_sql(sortable_ids, offset = 1)
  offset.upto(offset + sortable_ids.count - 1).reduce('position = CASE id ') do |sql, i|
    sql << "WHEN ? THEN #{i} "
  end << 'END'
end

Model.update_all [efficient_sort_sql(sortable_ids, offset), *sortable_ids], { id: sortable_ids }
UPDATE pancakes SET position = CASE id WHEN 5 THEN 1 WHEN 3 THEN 2 WHEN 4 THEN 3 WHEN 1 THEN 4 WHEN 2 THEN 5 WHERE id IN (5,3,4,1,2);