【发布时间】:2015-09-04 10:26:00
【问题描述】:
:parent has_many :children 我正在尝试检索父母的最大孩子的年龄作为parent 的属性。我愿意接受任何有效地实现这一目标的解决方案。
我尝试进行子查询的原因是让数据库执行n+1 开销,而不是为每个父项发出单独的数据库请求。两者都效率低下,但使用子查询似乎更有效。
# 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
【问题讨论】:
标签: sql ruby-on-rails-4 subquery select-n-plus-1