Rails加入了关联限制

时间:2014-02-19 10:59:10

标签: ruby-on-rails postgresql activerecord

我正在尝试对所有电台进行查询,并加入措施

但我只想要最新的措施(由created_at DESC排序),因为一个电台有数千种措施。

我试过

Station.joins(:measures).limit(1) 

但这只是限制了电台。

其他信息:

电台有很多措施

衡量属于电台

我已阅读Active Records docs,并且只有关于在关联中使用where条件的信息。

该应用仅针对Postgres,SQL已被接受。


修改: 除schema.rb之外添加:

  create_table "measures", force: true do |t|
    t.integer  "station_id"
    t.float    "speed"
    t.float    "direction"
    t.float    "max_wind_speed"
    t.float    "min_wind_speed"
    t.float    "temperature"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.float    "speed_calibration"
  end

  add_index "observations", ["created_at"], name: "index_observations_on_created_at", using: :btree
  add_index "observations", ["station_id"], name: "index_observations_on_station_id", using: :btree

  create_table "stations", force: true do |t|
    t.string   "name"
    t.string   "hw_id"
    t.float    "latitude"
    t.float    "longitude"
    t.float    "balance"
    t.boolean  "offline"
    t.string   "timezone"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "slug"
    t.boolean  "show",                         default: true
    t.float    "speed_calibration",            default: 1.0
    t.datetime "last_observation_received_at"
  end

加成 这是目前正在使用的hackhish代码:

def all_with_latest_measure
  if user_signed_in? && current_user.has_role?(:admin)
    stations = Station.all.load
  end
  stations ||= Station.where(show: true).load

  if stations.size
    ids = stations.map { |s| s.id }.join(',')
    where = "WHERE m.station_id IN(#{ids})" unless ids.empty?
    measures = Measure.find_by_sql(%Q{
    SELECT DISTINCT ON(m.station_id, m.created_at)
      m.*
    FROM measures m
    #{where}
    ORDER BY m.created_at DESC
    })

    stations.each do |station|
      # Setup has_many relationship between station and Measure
      # Prevents n+1 queries
      measure = Measures.find { |m| m.station_id == station.id  }
      if measure
        measure.station = station
        station.latest_measure = measure
      end
    end
  end
end

3 个答案:

答案 0 :(得分:4)

我相信Rails 4你可以在协会上应用范围:

class Stations
  has_many :measures, -> { order('created_at DESC').limit(1)  }
end

然后:

2.0.0-p353 :008 > Station.first.measures
  Station Load (0.1ms)  SELECT "stations".* FROM "stations" ORDER BY "stations"."id" ASC LIMIT 1
  Measure Load (0.1ms)  SELECT "measures".* FROM "measures" WHERE "measures"."station_id" = ? ORDER BY created_at DESC LIMIT 1  [["station_id", 1]]

编辑:实际上,如果您只需要最新版本,可以使用has_one。它适用于Rails 4和Rails 3,语法略有修改:

class Stations
  has_one :recent_measure, -> { order('created_at DESC')  }, class_name: 'Measure' # Rails 4
  has_one :recent_measure, order: 'created_at DESC', class_name: 'Measure' # Rails 3
end

答案 1 :(得分:0)

Station.joins(:measures).group(:station_id).order("measures.created_at DESC")

答案 2 :(得分:0)

如果计量数据是在特定时间间隔内进行的,则应按created_at字段过滤度量。