2013-03-23 55 views
1

我有两种型号 - QuestionAnswer如何查找关联计数等于0的模型的所有记录?

我想找到有0个答案的问题数量。

所以,我想这样的东西,没有工作:

Question.where("answers.count = 0").count 

Question.where("answers.count", 0).count 

Question.joins(:answers).where("answers.count == 0").count 

等少数排列。

我如何得到我想要的?

回答

3
Question.select('questions.*, COUNT(questions.id) AS question_count').joins('LEFT OUTER JOIN questions ON questions.answer_id = answers.id').group('answers.id').select { |a| a.question_count == 0}.count 

会得到你想要的。但这有点噩梦 - 我想知道我是否错过了一些东西?

如果你想要做大量复杂的查询,然后squeel值得一看 - https://github.com/ernie/squeel

或者,如果你只是想指望答案的数目,那么你可以使用一个counter_cache http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

这里有一个有关如何添加计数器缓存http://blog.obiefernandez.com/content/2011/08/adding-a-counter-cache-to-existing-records.html

编辑 由于博客帖子@boulder为指向纯粹的SQL答案

Question.joins('LEFT OUTER JOIN answers ON answers.question_id = questions.id').group('questions.id').having("count('answers.id') = 0").count 
+0

我只是想在命令行上做到这一点。似乎有点....矫枉过正。必须有一个更简单的方法来做到这一点...不是吗? – marcamillion 2013-03-23 13:26:21

+0

是的 - 我也有这种感觉,但我想不起来。 – Edward 2013-03-23 13:27:23

+0

计数器缓存一旦设置完成,就非常直观,并且完全符合您的需求。 – Edward 2013-03-23 13:28:00

4

虽然爱德华的答案的作品,你可以而且应该用纯SQL做到这一点:

Question.joins('LEFT OUTER JOIN answers.id ON answers.question_id = questions.id').group("questions.id").having("count('answers.id') = 0") 

但是,如果你只是想没有正确答案的问题的总数,我不认为你可以做到这一点ActiveRecord方法。您将需要自己构建sql语句。

Question.find_by_sql(
    "select count(id) as total from (
     select questions.*, count(answers.id) from questions 
     left outer join answers on answers.question_id = questions.id 
     group by questions.id having count(answers.id) = 0) 
    as noanswers").first.total 
+0

但是,如果你只是加入(:答案),这是一个内部连接,所以不会有没有答案的问题! – Edward 2013-03-23 13:30:58

+0

......就是这样问的。我收到一个空数组作为回应。 – marcamillion 2013-03-23 13:32:04

+1

问题。连接('LEFT OUTER JOIN answers.id ON answers.question_id = question.id')。group(“questions.id”)。having(“count('answers.id')= 0”) – Edward 2013-03-23 13:33:26

0

如果你只是在做它的命令行上,不关心性能,那么我只是做Question.all.map(&:ID) - Answer.all.map(& :question_id).uniq获取所有问题ID。基本上,你选择所有的问题,找到他们的问题ID,并从所有问题ID中减去该集合。剩下的是没有答案的问题。

0
Question.find_by_sql('select * from questions where (select count(*) from answers where question_id = question.id) = 0').count 
相关问题