重写object.count(条件:[])SQL查询

时间:2013-06-14 19:27:16

标签: sql ruby-on-rails ruby ruby-on-rails-3

我有问答模型,答案属于问题,问题有很多答案。答案有一个布尔:correct列,因此答案可以标记为正确。

下面的代码检查问题是否有正确答案,然后相应地显示不同的div。代码可以工作,但它会对数据库执行繁琐的计数查询,我希望避免这种情况。

有没有办法重写这个查询,还是最好在问题表中有一个列,当答案被标记为正确时,该列会切换为true?

<div class="<%= question.answers.count(conditions: ['correct = ?', true]) == 1 ? 'correct-answer' : 'no-correct-answer' %>">
  <%= question.answers_count %>
</div>

修改

感谢下面的人发布了答案,但即使在答案表上有一个questions_id索引,两个查询都使用了我想避免的计数查询,因为可能有很多答案需要循环通过

我的解决方案是在问题表上创建一个:正确的布尔列,当答案标记为/切换为正确时,它也会切换此列,因此在渲染视图时我不必执行任何动态SQL查询。

answer.rb

def toggle_correct(attribute)
    toggle(attribute).update_attributes({attribute => self[attribute]})
  end

def toggle_question_correct
    self.question.toggle_correct(:correct)
end

2 个答案:

答案 0 :(得分:2)

您正在计算问题的正确答案数量(即检查每个答案),而您只需要检查是否存在正确答案(即,一旦发现正确答案就停止)。这可以用exists?

编写
question.answers.exists?(:correct => true)

除非您对每个问题都有很多答案,否则它不应该显着改变响应时间。您说这部分代码是“费力的”,您应该检查是否在表question_id的列answers上创建了索引。没有它,question.answers会生成answers表的完整扫描。

答案 1 :(得分:1)

我建议你在Answer模型上创建两个范围

scope :correct, -> { where(correct: true) }
scope :correct, -> { where(correct: false) }

然后您可以选择计算correnct答案的问题:

question.answers.correct.count

您可能还想在问题

上创建方法
def has_correct_answer?
    ! answers.correct.count.zero?
end

如果您在单个页面上显示许多问题和答案,我建议使用where子句进行AR #include,这样可以减少SQL查询(http://guides.rubyonrails.org/active_record_querying.html#eager-loading-multiple-associations