Да, для этого вы можете использовать LEFT OUTER JOIN. Обычное ВНУТРЕННЕЕ СОЕДИНЕНИЕ будет включать только те строки, которые соответствуют условию соединения, ЛЕВОЕ СОЕДИНЕНИЕ будет включать совпадающие строки и конкретизировать несопоставленные строки, помещая NULL во все столбцы (файл документы PostgreSQL имеют разумное описание).
Итак, вы делаете LEFT JOIN, а затем ищете несопоставленную строку, ища NULL. SQL будет выглядеть примерно так:
select ...
from questions
left outer join user_questions on questions.id = user_questions.question_id
where user_questions.question_id is null
Это даст вам все вопросы, на которые нет ответов. В ActiveRecord вы можете сделать что-то вроде этого:
Question.joins('left outer join user_questions on question.id = user_questions.question_id')
.where(:user_questions => { :question_id => nil })
.limit(1)
Возможно, вы также захотите поиграть со случайным порядком, но это должно помочь вам начать. Если это не дает вам совпадения, вы можете получить случайный вопрос примерно так:
n = Questions.count
q = Questions.offset(rand(n)).limit(1)
Вы могли бы сделать то же самое с Questions.order('random()').limit(1)
, но ORDER BY random()
может быть неприятно с большой базой данных; получение подсчета должно быть довольно быстрым, поэтому случайный выбор в Ruby должен быть достаточно быстрым, и это не заставит вашу базу данных ненавидеть вас.
Также ознакомьтесь с документацией, чтобы узнать, как привести в порядок эти joins
, Я работаю с базой данных с немного нестандартной структурой, поэтому иногда мне приходится делать что-то длинное; ActiveRecord отказывается выполнять для меня LEFT JOIN, пока я не объясню это YMMV.
person
mu is too short
schedule
07.03.2012