1

My last post was on the best way to write a SQL query with conditions on a LEFT OUTER JOIN:
LEFT OUTER JOIN with conditions (where, order by)?

Now, I need to convert that good piece of SQL into a sweet Active Record Query (Rails 3). ;-)

I have 2 Models:

Training has_many :training_histories

TrainingHistory belongs_to :training

How can I write a scope to get the results the SQL below retrieve ?

SELECT tc.id, tc.name, tc.order, 
th.id as history_id, th.finished_at, th.score
FROM trainings tc
LEFT OUTER JOIN training_histories th ON th.training_id = tc.id 
    and th.id =
    (SELECT th1.id from training_histories th1 where th1.training_id = tc.id
     and th1.finished_at is not null
     order by th1.finished_at desc limit 1)
WHERE tc.id > 4
AND tc.id < 8
GROUP BY tc.id
ORDER BY tc.order_by ASC, tc.id ASC

I want to retrieve all the records of TRAININGS and add the last valid (aka finished) associated record of TRAINING_HISTORIES.

Any suggestions ?

Thank you

1
  • why not doing 2 select requests? Commented Aug 10, 2011 at 21:41

1 Answer 1

7

For rails 3, try this:

Training.select("trainings.id, trainings.name, trainings.order, 
                 trainings.id AS history_id, training_histories.finished_at,
                 training_histories.score").
         joins("LEFT OUTER JOIN training_histories 
                ON training_histories.training_id = trainings.id 
                AND training_histories.id = (SELECT th1.id FROM training_histories th1          
                                             WHERE th1.training_id = tc.id
                                             AND th1.finished_at IS NOT NULL
                                             ORDER BY th1.finished_at DESC LIMIT 1)").
         where("trainings.id > 4 AND trainings.id < 8").
         group("trainings.id").
         order("trainings.order_by ASC, trainings.id ASC")

Basically, you're just converting your pre-written query into Rails 3 finder methods.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.