Rails平均多列

时间:2014-02-04 00:19:22

标签: ruby-on-rails

我需要根据我的VPC控制器中几个表的params搜索找到多列的平均值,但是我在查看视图中的平均结果时遇到问题,而且从数据库中读取的搜索速度很慢。想知道下面要做的最佳方法。是否最好在模型中进行平均值? (不知道如何做到这一点)

模型

class Vpc < ActiveRecord::Base

 has_many :results

end


class Result < ActiveRecord::Base
  attr_accessible :trial_id, :variety_id, :year, :lint, :turnout, :length_decimal, :length_imperial, :strength, :uniformity, :micronaire, :manual_class

  belongs_to :trial, :primary_key => 'trial_id'
  belongs_to :variety, :primary_key => 'variety_id'
  belongs_to :vpc
  has_many :sites, :through => :trial
  has_many :growers, :through => :trial
  has_many :regions, :through => :sites

end

控制器

    class VpcController < ApplicationController

      add_breadcrumb "Home", :root_url
      add_breadcrumb "Variety Performance Comparison", :vpc_index_path


      def index
        all = Result.select(:variety_id)
        @variety = Variety.where(:variety_id => all).order('variety_name DESC')
        @years = Result.select('DISTINCT year') 
        @regions = Region.all
        @irrigations = Trial.select('DISTINCT irrigated').order('irrigated ASC')
      end

      def search
       if params[:variety_one] != params[:variety_two]
   @comparison = Result.group('trials.trial_id').having('COUNT(*) = 2').where(variety_id: [params[:variety_one], params[:variety_two]]).
   joins(:trial).where('trials.irrigated' => params[:irrigated], 'year' => params[:year]).joins(:regions).where('sites.region_id' => params[:regions])
   @vone = @comparison.where('variety_id = ?', params[:variety_one]).select('avg(lint) AS lintone')
   @vtwo = @comparison.where('variety_id = ?', params[:variety_two]).select('avg(lint) as linttwo')
   @count = @comparison.count('DISTINCT results.trial_id')
   @years = @comparison.where('results.year' => params[:year]).select('DISTINCT results.year')
   @region = @comparison.where('sites.region_id' => params[:regions]).joins(:regions).group('regions.region_id').select("DISTINCT regions.name")
       else
       redirect_to vpc_index_url, notice: "Can't compare the same variety"
       end
       @variety_one = Variety.where('variety_id = ?', params[:variety_one]).group('variety_name')
       @variety_two = Variety.where('variety_id = ?', params[:variety_two]).group('variety_name')
       add_breadcrumb "Results"
      end
    end

查看结果

<h2>VPC</h2>

<p>We found <%= @count.count %> trials that matched your options, spanning <%= @years.length %> years (<%= @years.map{|y| y.year}.join(", ") %>) and <%= @region.length %> regions (<%= @region.map{|r| r.trial.site.region.name}.join(", ") %>).</p>
<table class="table">
 <th></th>
 <% @variety_one.each do |v| %>
 <th><%= v.variety_name %></th>
 <% end %>
 <% @variety_two.each do |v| %>
 <th><%= v.variety_name %></th>
 <% end %>
<th>Difference</th>
<tr>
<td>Yield (bales/ha)</td>
<td><%= "%.2f" % (@vone.lintone/227) unless @vone.blank? %></td>
<td><%= "%.2f" % (@vtwo.lintwo/227) unless @vtwo.blank? %></td>
<td><%= "%.2f" % ((@vone.lintone/227) - (@vtwo.lintwo/227)) unless @lintone.blank? %></td>
</tr>
</tr>
</table>
    <hr>

    <div class="accordion" id="accordion2">
      <div class="accordion-group">
        <div class="accordion-heading">
          <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">
            <b>Overview of results</b> <span class="pull-right"><i class="icon-chevron-down"></i></span>
          </a>
        </div>
        <div id="collapseOne" class="accordion-body collapse">
          <div class="accordion-inner">
            <table class="table">
                    <th>Year</th>
                    <th>Site</th>
                    <th>Region</th>
                    <th>Grower</th>
                    <% @comparison.each do |v| %>
                    <tr>
                    <td><%= link_to v.trial.year, trial_trials_path(trial_id: v.trial_id) %></td>
                    <td><%= link_to v.trial.site.site_name, trial_trials_path(trial_id: v.trial_id) unless v.trial.site.blank? %></td>
                    <td><%= link_to v.trial.site.region.name, trial_trials_path(trial_id: v.trial_id) unless v.trial.site.blank? %></td>
                    <td><%= link_to v.trial.grower.full_name, trial_trials_path(trial_id: v.trial_id) unless v.trial.grower.blank? %></td>
                    </tr>
                    <% end %>
                    </table>
          </div>
        </div>
      </div>

SQL错误

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS lintone) AS count_avg_lint_as_lintone, avg(lint) AS lintone, trials.trial_id ' at line 1: SELECT COUNT(avg(lint) AS lintone) AS count_avg_lint_as_lintone, avg(lint) AS lintone, trials.trial_id AS trials_trial_id FROM `results` INNER JOIN `trials` ON `trials`.`trial_id` = `results`.`trial_id` INNER JOIN `trials` `trials_results_join` ON `trials_results_join`.`trial_id` = `results`.`trial_id` INNER JOIN `sites` ON `sites`.`site_id` = `trials_results_join`.`site_id` INNER JOIN `regions` ON `regions`.`region_id` = `sites`.`region_id` WHERE `results`.`variety_id` IN (2300, 2255) AND `trials`.`irrigated` IN (0, 1, 2) AND `results`.`year` IN (2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013) AND `sites`.`region_id` IN (1, 2, 3, 4, 5, 6, 7, 8) AND (variety_id = '2300') GROUP BY trials.trial_id HAVING COUNT(*) = 2

1 个答案:

答案 0 :(得分:2)

看着你庞大的控制器,我建议如下:

@comparison = Result.group('trials.trial_id').having('COUNT(*) = 2').where(variety_id: [params[:variety_one], params[:variety_two]]).
joins(:trial).where('trials.irrigated' => params[:irrigated], 'year' => params[:year]).joins(:regions).where('sites.region_id' => params[:regions])
@count = @comparison.count('DISTINCT results.trial_id')
@years = @comparison.where('results.year' => params[:year]).select('DISTINCT results.year')
@region = @comparison.where('sites.region_id' => params[:regions]).joins(:regions).group('regions.region_id').select("DISTINCT regions.name")

保持该块相同,但创建一个迁移以添加索引以提高性能。

你不应该多次调用平均值,而是选择你想要的值

@vone = @comparison.where('variety_id = ?', params[:variety_one]).select(avg(lint) as lint, avg...
@vtwo = @comparison.where('variety_id = ?', params[:variety_two]).select(avg(lint) as lint, avg...)

现在,在您的视图中,您可以获得所需的属性。

之后,查看日志以查看是否有任何可以减少的N + 1。