I have three tables:
- Users
- Questions
-
User_Questions
1.user questions has the columns user_id, question_id, and answer
I want to find a random question that has not been answered and thus does not have a row in the user_questions table.
If every question has been answered, then return any random question.
I’m told this can be done with an OUTER JOIN, but I’m a SQL noob and I’m not sure how to do that in Rails.
This is what I have:
def next_question
q = Question.all - Question.joins(:user_questions).where
(user_questions: { user_id: user_id })
q = Question.all if q.empty?
return q[rand(q.size)]
end
There’s hardly ever a good reason for calling the
allmethod on a model class. This loads every single record in the database of that type into memory, and unless you’re absolutely certain this is a small set of records, you could potentially hang your entire system. Even then it’s extremely bad form to load in everything and then cherry pick one thing and discard the rest. It’s like ordering one of every single item from Amazon, picking out the pen you want, and throwing the rest of the delivery in the trash.What you probably want is something where you randomly select one record that has not been assigned yet. That probably looks something like this:
The problem with a
JOINis that you’re going to find records that have matches in theuser_questionstable and not the inverse.This query presumes that the number of questions answered by a user is relatively small or that
NOT INcould get dramatically more expensive.