views:

3247

answers:

2

I want this SQL query to be written in rails controller using find
select id,name from questions where id not in (select question_id from levels_questions where level_id=15)
How will I do this?I am using Rails framework and MySQL db
thanks in advance.

+3  A: 
Question.find_all_by_sql('select id,name from questions where id not in (select question_id from levels_questions where level_id=15)')

This is admittedly non-ActiveRecord-ish, but I find that complicated queries such as this tend to be LESS clear/efficient when using the AR macros. If you already have the SQL constructed, you might as well use it.

Some suggestions: encapsulate this find call in a method INSIDE the Question class to hide the details from the controller/view, and consider other SQL constructions that may be more efficient (eg, an OUTER JOIN where levels_questions.question_id is null)

joshng
of course. this is better.
Ryan Oberoi
cool... first my answer was selected, then I find I have a -1 and I've been DEselected. and now the author of the selected answer says mine is better..? heh, ouch :-}
joshng
well. I said yours was better when I saw it the first time, not after. I think your one-liner is superior. I gave you a +1 for your answer. I think you need to modify your answer to replace model.find_by_sql with Question.find_all_by_sql, then it will serve the author's purpose.
Ryan Oberoi
thanks, ryan. I'm not bitter, it's just my REPUTATION at stake... :-D
joshng
+4  A: 

Simple way:

ids = LevelsQuestion.all(:select => "question_id", 
        :conditions => "level_id = 15").collect(&:question_id)
Question.all(:select => "id, name", :conditions => ["id not in (?)", ids])

One shot:

Question.all(:select => "id, name",
:conditions => ["id not in (select question_id from levels_questions where level_id=15)"])
Ryan Oberoi
can this be given in the options_from_collection_for_select in the select_tag?
Nave
I just edited it to change it from find to all. Select the version you like. I guess something made you change your mind. I like the other solution as well. Let us know why you selected my answer over the other one.
Ryan Oberoi