我在使用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'include'功能,这样我就不会遇到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
我如何编写查询以便完成目标并限制我点击数据库的次数(理想情况下是包含)?
答案 0 :(得分:1)
在连接查询的情况下,setState
要求关联表中的额外列(即includes
),以便在没有其他查询的情况下构建关联的对象。通常情况下,这是一个受欢迎的优化,但对于tasks
条款,最终会出现无效GROUP BY
。
在您的情况下,您需要一个完全独立的查询来加载关联,因此SELECT
是更好的选择。
preload