在postgres / activerecord中使用非主键进行分组

时间:2013-08-27 13:16:09

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

我有一个模型Lap:

class Lap < ActiveRecord::Base
  belongs_to :car

  def self.by_carmodel(carmodel)
    scoped = joins(:car_model).where(:car_models => {:name => carmodel})
    scoped
  end

  def self.fastest_per_car
    scoped = select("laps.id",:car_id, :time, :mph).group("laps.id", :car_id, :time, :mph).order("time").limit(1)
    scoped
  end
end

我想只返回每辆车最快圈速。

所以,我需要通过Lap.car_id对Laps进行分组,然后只返回基于该车的最快单圈时间,这将由Lap.time列确定

基本上我想在控制器中堆叠我的方法:

@corvettes = Lap.by_carmodel("Corvette").fastest_per_car

希望这有意义......

当试图仅运行 Lap.fastest_per_car 时,我将所有内容限制为1个结果,而不是每个Car的1个结果。

我要做的另一件事是添加“laps.id”:id在我的结果中也显示为空。如果我只选择(:id),那就是说不明确的

3 个答案:

答案 0 :(得分:1)

我认为一个不错的方法是基于高效的S​​QL语法添加一个where子句,以便返回单个最快圈速。

像这样的相关子查询...

select ...
from   laps
where  id = (select   id
             from     laps laps_inner
             where    laps_inner.car_id = laps.car_id
             order by time asc,
                      created_at desc
             limit    1)

由于需要在created_at上打破中断,这有点复杂。

轨道范围只是:

where("laps.id = (select   id
                  from     laps laps_inner
                  where    laps_inner.car_id = laps.car_id
                  order by time asc,
                           created_at desc
                  limit    1)")

car_id上的索引非常重要,如果这是(car_id,time asc)的综合索引,那就更好了。

答案 1 :(得分:0)

您正在使用限制,它将返回一个值。每辆车不是一个值。要为每圈返回一个汽车价值,你只需要加入表格并按一组列来识别一圈(id是最简单的)。

此外,您可以通过以下方式与ActiveRecord友好友好:

class Lap < ActiveRecord::Base
  belongs_to :car

  def self.by_carmodel(carmodel)
    joins(:car_model).where(:car_models => {:name => carmodel})
  end

  def self.fastest_per_car
    joins(:car_model)
      .select("laps.*, MIN(car_models.time) AS min_time")
      .group("laps.id")
      .order("min_time ASC")
  end
end

答案 2 :(得分:0)

这就是我所做的和它的工作。如果有更好的方法可以解决这些问题,请发表您的答案:

在我的模型中:

def self.fastest_per_car
    select('DISTINCT ON (car_id) *').order('car_id, time ASC').sort_by! {|ts| ts.time}
end