我在使用rails activerecord查询时遇到问题。
我有2张桌子。
一个项目:
id | name | created_at | updated_at
一个用于项目报告:
id | project_id | number | created_at | updated_at
Project的相应类:
class Project < ActiveRecord::Base
has_many :project_reports
def latest_report_number
project_reports.last.number
end
end
和ProjectReports:
class ProjectReport < ActiveRecord::Base
belongs_to :project
end
我正在尝试编写查询以获取项目列表和该项目的最新报告。
我可以通过以下方式执行此操作,但这会导致N + 1情况:
Project
.select("projects.*, max(project_reports.created_at) as latest_report")
.joins(:project_reports)
.order("latest_report desc")
.group("projects.id")
.map { |p| "#{p.name}: #{p.latest_report_number}" }
因此,我想使用rails的“ includes”功能,以免遇到N + 1情况:
Project
.select("projects.*, max(project_reports.created_at) as latest_report")
.joins(:project_reports)
.order("latest_report desc")
.group("projects.id")
.includes(:project_reports) # <----
.map { |p| "#{p.name}: #{p.latest_report_number}" }
这导致我的查询不再起作用:
PG::GroupingError: ERROR: column "project_reports.id" must appear in
the GROUP BY clause or be used in an aggregate function
如何编写查询,以便既完成目标又限制我访问数据库的次数(理想情况下是包含)?
在includes
联接查询的情况下,从关联表中请求额外的列(即tasks
),以便在不进行额外查询的情况下构建关联的对象。通常,这是一个受欢迎的优化,但是对于GROUP BY
子句,您最终会看到invalid SELECT
。
在您的情况下,您需要一个完全独立的查询来加载关联,因此preload
是一个更好的选择。
Project
.select("projects.*, max(project_reports.created_at) as latest_report")
.joins(:project_reports)
.order("latest_report desc")
.group("projects.id")
.preload(:project_reports)
.map { |p| "#{p.name}: #{p.latest_report_number}" }
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句