A:parent has_many :children
と私は、親の最年長の子供の年齢を の属性として取得しようとしていますparent
。私は、それを効率的に達成するあらゆるソリューションを受け入れます。
サブクエリを実行しようとしている理由は、n+1
親ごとに個別の DB 要求を行うのではなく、DB にオーバーヘッドを任せるためです。どちらも非効率的ですが、サブクエリを使用する方が効率的です。
# attributes: id
class Parent < ActiveRecord::Base
has_many :children
# Results in an (n+1) request
def age_of_oldest_child
children.maximum(:age)
end
end
# attributes: id, parent_id, age
class Child < ActiveRecord::Base
belongs_to :parent
end
ユースケースの例:
parent = Parent.first.age_of_oldest_child # => 16
parents = Parent.all
parents.each do |parent|
puts parent.age_of_oldest_child # => 16, ...
end
私の試み:
sql = "
SELECT
(SELECT
MAX(children.age)
FROM children
WHERE children.parent_id = parents.id
) AS age_of_oldest_child
FROM
parents;
"
Parent.find_by_sql(sql)
これは、すべての親の最大年齢の配列を返します。これを 1 つの親だけに制限するか、すべての親を取得するときに親の属性として含めるようにしたいと考えています。
更新 2015-06-19 11:00
これが私が思いついた実行可能な解決策です。より効率的な代替手段はありますか?
class Parent < ActiveRecord::Base
scope :with_oldest_child, -> { includes(:oldest_child) }
has_many :children
has_one :oldest_child, -> { order(age: :desc).select(:age, :parent_id) }, class_name: Child
def age_of_oldest_child
oldest_child && oldest_child.age
end
end
使用例:
# 2 DB queries, 1 for parent and 1 for oldest_child
parent = Parent.with_oldest_child.find(1)
# No further DB queries
parent.age_of_oldest_child # => 16