ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql-Rails 3-将多个计数转换为单个查询-OrderedHash

2019-12-08 09:17:26  阅读:231  来源: 互联网

标签:activerecord optimization count ruby-on-rails mysql


我有一个做傻事的初始化方法.我需要将其优化为一个查询,但是我的SQL技能目前使我感到失望.我已经考虑过使用GROUP BY和UNION以及各种各样的东西,但是我只是让自己更加困惑.我将其遗赠给社区,以得出一些见解:

Class Stats
  # Turn these three queries into one query that we can then
  # load into the three different instance variables
  def initialize(question)
    # Integer = total number of answers for this question
    @total = total_answers(question.id)

    # Hash keyed by 0 (incorrect answers) and 1 (correct answers)
    @stats_total = load_stats_total(question.id) if @total > 0

    # Hash keyed by answer_id with values = total number of answers
    @stats_answers = load_stats_answers(question.id) if @total > 0
  end

  # Returns an int = the total number of answer attempts for
  # this question (right + wrong user_answers)
  # Excludes anonymous users
  def total_answers(question_id)
    UserAnswer.count(:conditions => ['u.anonymous = 0 AND q.id = ?', question_id], :joins => 'JOIN answers a ON user_answers.answer_id = a.id JOIN questions q ON q.id = a.question_id JOIN users u ON u.id = user_answers.user_id')
  end

  # Returns an OrderedHash =
  # {"0" => number of wrong user_answers for this question,
  #  "1" => number of correct user_answers for this question}
  # Excludes anonymous users
  def load_stats_total(question_id)
    UserAnswer.count(:conditions => ['u.anonymous = 0 AND q.id = ?', question_id], :joins => 'JOIN answers a ON user_answers.answer_id = a.id JOIN questions q ON q.id = a.question_id JOIN users u ON u.id = user_answers.user_id', :group => 'a.correct')
  end

  # Returns an OrderedHash =
  # {
  #  some_answer_id => total number of user_answers for this answer,
  #  some_other_answer_id => total number of user_answers for this answer
  #  ...
  # }
  # Excludes anonymous users
  def load_stats_answers(question_id)
    UserAnswer.count(:conditions => ['u.anonymous = 0 AND q.id = ?', question_id], :joins => 'JOIN answers a ON user_answers.answer_id = a.id JOIN questions q ON q.id = a.question_id JOIN users u ON u.id = user_answers.user_id', :group => 'a.id')
  end
end

如果有人有任何想法,将不胜感激!
谢谢.

解决方法:

我认为您无法在一个查询中做到这一点.
至少并非没有编写纯sql.

但是,让我们尝试在ActiveRecord中找到一个不错的解决方案

首先,让我们尝试删除一些sql

UserAnswer.count(:conditions => ['u.anonymous = 0 AND q.id = ?', question_id], :joins => 'JOIN answers a ON user_answers.answer_id = a.id JOIN questions q ON q.id = a.question_id JOIN users u ON u.id = user_answers.user_id')

可以改写

UserAnswer.joins(:user).where(:users => {:anonymous => false})\
  .joins(:answer => :question).where(:questions => {:id => question_id})\
  .count

让我们将范围保存为魔术私有方法magic_scope

您当前的方法成为

def total_answers(question_id)
  magic_scope(question_id).count
end

def load_stats_total(question_id)
  magic_scope(question_id).count(:group => "answers.correct")
end

def load_stats_answers(question_id)
  magic_scope(question_id).count(:group => "answers.id")
end

当然,值得注意的是,total_answers方法可以通过汇总两个load_stats_ *方法的结果得出.

如果ActiveRecord更加聪明,我们可以做

def all_the_magic(question_id)
  magic_scope(question_id).count(:group => ["answers.correct", "answers.id"])
end

这样一来,我们就能获得所需的所有数据.

但据我所知,目前尚不可能.

但我希望这能使您更接近.

标签:activerecord,optimization,count,ruby-on-rails,mysql
来源: https://codeday.me/bug/20191208/2090355.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有