从数据库表(Rails)生成每日平均值数组



上下文:尝试为db表中的每个created_at天生成一个包含1个元素的数组。每个元素都是具有该created_at天的记录的points(整数)列的平均值。稍后将对此进行绘图,以显示每天的平均点数。

结果:我已经成功地做到了这一点,但要生成所需的结果,感觉需要不必要的代码量。

代码:

def daily_avg
    # get all data for current user
    records = current_user.rounds
    # make array of long dates
    long_date_array = records.pluck(:created_at)
    # create array to store short dates
    short_date_array = []
    # remove time of day
    long_date_array.each do |date|
        short_date_array << date.strftime('%Y%m%d')
    end 
    # remove duplicate dates
    short_date_array.uniq!
    # array of avg by date
    array_of_avg_values = []
    # iterate through each day
    short_date_array.each do |date|
        temp_array = []
        # make array of records with this day
        records.each do |record|
            if date === record.created_at.strftime('%Y%m%d')
                temp_array << record.audio_points
            end
        end
        # calc avg by day and append to array_of_avg_values
        array_of_avg_values << temp_array.inject(0.0) { |sum, el| sum + el } / temp_array.size
    end
    render json: array_of_avg_values
end

问题:我认为这是一个常见的extraction问题,需要很多应用程序来解决,所以我想知道是否有一个已知的可重复模式来解决这样的问题?

还是一种更优化的方法来解决这个问题?

(我只是一个初级开发人员,所以如果您能提供任何建议,我们将不胜感激!)

是的,当你可以直接转到SQL时,这是很多不必要的东西(我假设你的应用程序中有一个名为Round的类):

class Round
  DAILY_AVERAGE_SELECT = "SELECT 
      DATE(rounds.created_at) AS day_date,
      AVG(rounds.audio_points) AS audio_points
    FROM rounds
    WHERE rounds.user_id = ?
    GROUP BY DATE(rounds.created_at) 
"
  def self.daily_average(user_id)
    connection.select_all(sanitize_sql_array([DAILY_AVERAGE_SELECT, user_id]), "daily-average")
  end
end

直接在数据库中执行此操作将比现在在ruby中执行更快(并且包含更少的代码)。

我建议你这样做:

grouped =
records.order(:created_at).group_by do |r|
   r.created_at.strftime('%Y%m%d')
end

首先,在这里,您生成了与您希望在第一近似中获得的SQL接近的正确SQL,然后通过转换为仅日期的created_at字段对结果记录进行分组。

points =
grouped.map do |(date, values)|
   [ date, values.reduce(0.0, :audio_points) / values.size ]
end.to_h
# => { "1-1-1970" => 155.0, ... }

然后通过数组重新映射分组后的散列,用audio_points计算平均值。

您可以使用group和AR中内置的计算方法:http://guides.rubyonrails.org/active_record_querying.html#grouphttp://guides.rubyonrails.org/active_record_querying.html#calculations

最新更新