Rails 3 - 将多个计数转换为单个查询 - OrderedHash
我有一个初始化方法,它做了一件愚蠢的事情。我需要将其优化为一个查询,但目前我的 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
如果有人有任何想法,我们将不胜感激! 谢谢。
I've got an initializer method that does a silly thing. I need to optimize it down to one query, but my SQL skills are failing me at the moment. I've conceived of using GROUP BY and UNION and all sorts of things, but I just made myself more confused. I bequeath this to the community to shed some insight:
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
If anyone has any thoughts, they'd be greatly appreciated!
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您无法在一个查询中干净地完成此操作。
至少在不编写纯sql的情况下是这样。
但是让我们尝试在 ActiveRecord 中找到一个不错的解决方案
首先,让我们尝试删除一些
可以重写的
sql让我们将此范围保存为一个神奇的私有方法
magic_scope
您当前的方法变得
显着,当然,
total_answers
方法可以通过对任一load_stats_*
方法的结果求和来派生。如果 ActiveRecord 更聪明一点,我们可以做到
这一点,这将为我们提供在一次查询中执行此操作所需的所有数据。
但据我所知,目前这是不可能的。
但我希望这能让你更接近。
I don't think you can do this cleanly in one query.
At least not without writing pure sql.
But lets try and find a nice solution in ActiveRecord
First of all, let's try to remove some of the sql
can be rewritten
lets just save this scope as a magic private method
magic_scope
your current methods become
notably, of course, the
total_answers
method can be derived from summing up the results from either of theload_stats_*
methods.If ActiveRecord was a bit more clever we could do
which would give us all the data we needed to do it in one query.
but as far as I'm aware that's not currently possible.
But I hope this gets you nearer.