3

I am struggling to use Rails' ActiveRecord query interface to replicate a query that has an inner join subquery. How would I replicate the following:

SELECT ass.name, COUNT(DISTINCT a.question_id) AS 
  answered_questions, tq.total_questions
  FROM assessments AS ass
  INNER JOIN  (SELECT ass.id, COUNT(q.id) AS total_questions FROM                         
    questions AS q INNER JOIN assessments AS ass ON ass.id=q.assessment_id 
    GROUP BY 
    ass.id) as tq ON tq.id=ass.id
  INNER JOIN questions AS q ON q.assessment_id=ass.id
  INNER JOIN answers AS a ON a.assessment_id=ass.id AND a.question_id=q.id
  INNER JOIN org_assesments AS oa ON ass.id=oa.assessment_id
  INNER JOIN users AS u ON oa.org_id=u.org_id AND       
    a.user_id=u.id
  WHERE  u.id=1
  GROUP BY ass.name, tq.total_questions
  ORDER BY ass.created_at DESC
  LIMIT 10

I don't seem to be able to get this to work with the subquery using the query builder. Without the subquery I have this, which works and gives me the assessment title and number of questions answered:

Question.joins(:assessment => {:org_assessments => {:org => :users}}).joins(:answers)
                 .where(answers:{:user_id => params[:id]})
                 .distinct('answers.question_id').group(['assessments.name']).count()

How can I write this to include the subquery as in the original SQL above?

3
  • shouldn't that start with Assessment.joins....? Commented May 31, 2017 at 11:42
  • Does this work Assessment.find_by_sql("Above query")? Commented May 31, 2017 at 11:44
  • I think you should query on assessment instead of question, like this :-> Assessment.joins(:questions,:answer, org_assesments: :user).where(users:{id: 1}).distinct('answers.question_id').group(['assessments.name']).order('assessments.created_at DESC').count() Commented May 31, 2017 at 12:19

1 Answer 1

11

You may send the subquery as a string to the joins method:

sub_query =
  TotalQuestion.
    joins(:assessments).
    group('assessments.id').
    select('assessments.id, COUNT(q.id) as total_questions').to_sql

Question.joins("(#{sub_query}) as tq on tq.id=ass.id")

And you can combine it with the other parts of the query:

Question.
    joins(:assessment => {:org_assessments => {:org => :users}}).joins(:answers).
    joins("(#{sub_query}) as tq on tq.id=ass.id").
    where(answers:{:user_id => params[:id]}).
    distinct('answers.question_id').group(['assessments.name']).count()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.