2011-06-13 82 views
3

我有一個初始化方法,做一個愚蠢的事情。我需要優化到一個查詢,但我的SQL技術目前正在失敗。我已經設想過使用GROUP BY和UNION以及各種各樣的東西,但是我只是讓自己變得更加困惑。我遺留給社區的一些見解:Rails 3 - 將多個計數轉換爲一個查詢 - OrderedHash

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 

如果有人有任何想法,他們將不勝感激! 謝謝。

回答

2

我不認爲你可以在一個查詢中乾淨地做到這一點。 至少不是沒有寫純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

你R當前方法成爲

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 

這將使我們所有我們需要做的是在一個查詢的數據。

但據我所知,目前不可能。

但我希望這能讓你更接近。

+0

Welp,我想現在已經夠好了。謝謝馬修! – wulftone 2011-07-07 05:17:03