Ruby on rails 你能用rails中的find_进行分组吗?

Ruby on rails 你能用rails中的find_进行分组吗?,ruby-on-rails,postgresql,Ruby On Rails,Postgresql,我正在尝试编写一个函数,该函数通过一个非常大的表中的一些列对数百万行进行分组。有没有办法让find_each来处理这个问题,或者是不可能的,因为我不想按id列排序 我的查询的SQL是: 按可派生类型从mytable组中选择可派生类型、可派生id,按mytable.id ASC选择可派生id顺序 rails find_使用reorder语句自动添加ORDERBY子句。我已尝试将SQL更改为: 选择MAXid作为mytable.id,可派生类型,按可派生类型从mytable组中选择可派生类型,按my

我正在尝试编写一个函数,该函数通过一个非常大的表中的一些列对数百万行进行分组。有没有办法让find_each来处理这个问题,或者是不可能的,因为我不想按id列排序

我的查询的SQL是: 按可派生类型从mytable组中选择可派生类型、可派生id,按mytable.id ASC选择可派生id顺序

rails find_使用reorder语句自动添加ORDERBY子句。我已尝试将SQL更改为:

选择MAXid作为mytable.id,可派生类型,按可派生类型从mytable组中选择可派生类型,按mytable.id ASC选择可派生类型顺序


但这也不行。除了编写我自己的find\u each函数或在批处理中重写private batch\u order函数之外,还有其他想法吗?rb?

我不确定我是否100%清楚您要做什么,但您的查询看起来与执行聚合操作一样

SELECT derivable_type, derivable_id FROM "mytable" GROUP BY derivable_type, derivable_id ORDER BY "mytable"."id" ASC;
---- vv
SELECT DISTINCT(derivable_type, derivable_id) FROM "mytable" ORDER BY "mytable"."id" ASC;
如果Mytable是您的模型,您应该能够使用Active Record和find_each来完成此任务:

Mytable.all.group(:derivable_type, :derivable_id).distinct.find_each
# gives => #<Enumerator: #<ActiveRecord::Relation [...]>:find_each({:start=>nil, :finish=>nil, :batch_size=>1000, :error_on_ignore=>nil})>

至少有两种方法可以解决此问题:

I.使用子查询:

二,。为每个函数编写自定义find_


非常感谢你的想法。我也尝试了你建议的SQL和活动记录代码,但我仍然得到了与我原来帖子中相同类型的错误。此错误为:错误:对于SELECT DISTINCT,ORDER BY表达式必须出现在SELECT listHrmm中。。您能提供您的表模式吗?我想尝试在本地复制它。
# query the table and select id, derivable_type and derivable_id
my_table_ids = MyTable
  .group("derivable_type, derivable_id")
  .select("MAX(id) AS my_table_id, derivable_type, derivable_id")

# use subquery to allow rails to use ORDER BY in find_each 
MyTable
  .where(id: my_table_ids.select('my_table_id'))
  .find_each { |row| do_something(row) } 
rows = MyTable
  .group("derivable_type, derivable_id")
  .select("derivable_type, derivable_id")

find_each_grouped(rows, ['derivable_type', 'derivable_id']) do |row| 
  do_something(row)
end

def find_each_grouped(rows, columns, &block)
  offset = 0
  batch_size = 1_000
  loop do
    batch = rows
      .order(columns)
      .offset(offset)
      .limit(limit)

    batch.each(&block)

    break if batch.size < limit
    offset += limit
  end
end