2014-03-21 4 views
0

Как я могу улучшить этот запрос?Улучшить запрос activerecord

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? Как я могу это сделать? Любые улучшения скорости или структуры приветствуются.

спасибо.

+1

Это было бы более подходящим для проверки кода, чем SO –

ответ

1

Поскольку в вашем сценарии большинство запросов находятся на поле position, я бы предложил сделать и индексировать это поле.

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, Rails и Hash#selectEnumerable#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) 
...