改进activerecord查询

时间:2014-03-21 11:44:39

标签: ruby activerecord ruby-on-rails-4

如何改进此查询?

 f, s, t, ft, et, tf = [], [], [], [], [], []
 reports = pros.each do |pro|
  pro_report = pro.project_reports.where(project_id: project_id).size
  f << pro_report.where(position: 1).size
  s << pro_report.where(position: 2).size
  t << pro_report.where(position: 3).size
  ft << pro_report.where('position BETWEEN ? AND ?', 4, 10).size
  et << pro_report.where('position BETWEEN ? AND ?', 11, 20).size
  tf << pro_report.where('position BETWEEN ? AND ?', 21, 50).size
 end
{f: f.sum, s: s.sum, t: t.sum, ft: ft.sum, et: et.sum, tf: tf.sum}

创建Postgres VIEW是个好主意吗?我怎样才能做到这一点? 欢迎任何速度或结构的改进。

谢谢。

2 个答案:

答案 0 :(得分:1)

由于在您的方案中,大多数查询都在position字段上,因此我建议在该字段上进行制作和索引。

答案 1 :(得分:1)

不需要循环。如下所示

pro_ids = pros.map(&:id)
pro_reports = ProjectReport.where(project_id: pro_ids)
f = pro_reports.where(position: 1).size
s = pro_reports.where(position: 2).size
t = pro_reports.where(position: 3).size
ft = pro_reports.where('position BETWEEN ? AND ?', 4, 10).size
et = pro_reports.where('position BETWEEN ? AND ?', 11, 20).size
tf = pro_reports.where('position BETWEEN ? AND ?', 21, 50).size

请记住在位置列中有适当的索引 - 在这种情况下是必须的。

或者,您可以按位置对数据库分组执行单个查询,然后使用Ruby Hash#select和Rails Enumerable#sum来获取所需的值:

pro_ids = pros.map(&:id)
hash_pos_count = ProjectReport.where(project_id: pro_ids).group(:position).size

f = hash_pos_count.select{ |k, v| k == 1 }.first.last
...
ft = hash_pos_count.select{ |k, v| k >= 3 && k <= 10 }.sum(&:last) 
...