Rails - 活动记录:添加额外的选择列以查找(:全部)

ice*_*ice 10 activerecord ruby-on-rails rails-activerecord

我想向sum(time_entries.hours)sql select 添加新列我正在查询这样的条目:

issues = Issue.visible.where(options[:conditions]).all(
    :include => ([:status, :project, :time_entries] + (options[:include] || [])).uniq,
    :conditions => statement,
    :order => order_option,
    :joins => query_joins(order_option.join(',')),
    :limit => options[:limit],
    :offset => options[:offset],
    :group => "#{Issue.table_name}.id"
)
Run Code Online (Sandbox Code Playgroud)

它生成这个选择:

SELECT
 "issues"."id"                         AS t0_r0,
 ...
 "time_entries"."hours"                AS t3_r4,
 ...
 "versions"."sharing"                  AS t8_r9
FROM "issues"
 LEFT OUTER JOIN "projects" ON "projects"."id" = "issues"."project_id"
 LEFT OUTER JOIN "issue_statuses" ON "issue_statuses"."id" = "issues"."status_id"
 LEFT OUTER JOIN "time_entries" ON "time_entries"."issue_id" = "issues"."id"
 LEFT OUTER JOIN "users" ON "users"."id" = "issues"."assigned_to_id"
 LEFT OUTER JOIN "trackers" ON "trackers"."id" = "issues"."tracker_id"
 LEFT OUTER JOIN "enumerations"
   ON "enumerations"."id" = "issues"."priority_id" AND "enumerations"."type" IN ('IssuePriority')
 LEFT OUTER JOIN "issue_categories" ON "issue_categories"."id" = "issues"."category_id"
 LEFT OUTER JOIN "versions" ON "versions"."id" = "issues"."fixed_version_id"
WHERE "issues"."id" IN (1) AND (projects.status <> 9 AND projects.id IN (SELECT
                                                                       em.project_id
                                                                     FROM enabled_modules em
                                                                     WHERE em.name =     'issue_tracking')) AND
  ((issues.status_id IN (SELECT
                           id
                         FROM issue_statuses
                         WHERE is_closed = 'f')))
GROUP BY issues.id
ORDER BY issues.id
 DESC
Run Code Online (Sandbox Code Playgroud)

我尝试将:select=>"*, sum(time_entries.hours)"hash参数插入到all方法中,但是没有效果.

如何在此选择中添加新列?此外,我需要保留所有当前列,因为它们用于过滤器.有没有办法没有用手指定所有列?

更新: Ruby 1.9.3 Rails 3.2.13

Kap*_*ssi 11

表名从Redmine看起来像.我最近遇到了类似的问题.我发现所选择的柱子来自可见范围.我无法确定原因,但没有它,"选择"选项按预期工作.

运用

Issue.select("#{Issue.table_name}.*, sum(#{TimeEntries.table_name}.hours AS total_hours").where("#{your_conditions}").group(:id).all
Run Code Online (Sandbox Code Playgroud)

应该给你你想要的数据.附加列可以作为Issue属性直接访问:

Issue.total_hours
Run Code Online (Sandbox Code Playgroud)

编辑:

如果无法同时选择所有"问题"字段(用于创建完整的"问题"对象)和总和,则需要在获得所需问题后使用第二个语句.

issues = Issue.visible.where("#{issue_conditions}").all
issue_ids = issues.map(&:id)
# if you do not need the issue objects, use .pluck(:id) instead of .all

spent_hours = TimeEntries.select('issue_id, sum(hours)')
                         .where(:issue_id => issue_ids)
                         .where("#{other_time_conditions}")
                         .group(:issue_id).all
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用Redmines Issue类中包含的便捷功能.使用此选项可使软件为您完成工作:

i = Issue.includes(:time_entries).find(1)
i.total_spent_hours
Run Code Online (Sandbox Code Playgroud)

包含确保计算不会再次访问数据库,因为已加载所有相关关联.


Ryo*_*Ryo 5

有点旧,但这样的东西应该可以工作。(在 Rails 5 左右)

issues = Issue. ...

issues.select(
  issues.arel.projections,
  TimeEntry.arel_table[:hours].sum
)
Run Code Online (Sandbox Code Playgroud)