views:

31

answers:

2

Hi everybody,

I have one model, which I save changes witch happens to certain person. I want to get now the latest state of all person.

so I need to: - order: created_at asc. - find_all: limit: one change each person

how can I accomplish that?

Thanks, Markus

+1  A: 

You need to use :group, which translates to a GROUP BY statement in SQL.

YourModel.all { :order => 'created_at DESC', :group => :person_id } 
Jordan
ORDER is applied after GROUP. So the results returned will not contain the last state.
KandadaBoggu
You are correct, KandadaBoggu. I'm pretty sure, however, that there's a solution using GROUP BY and MAX that would not require a subquery.
Jordan
To get all the fields of a matching row in the OrderState table you have to use a query. This is a classic problem. E.g: List the employee details with highest salary in each department etc.
KandadaBoggu
+1  A: 

Try this:

person_hash = OrderState.maximum(:created_at, :group => :person_id)
person_hash.each |person_id, created_at|
  state = OrderState.find_by_person_id_and_created_at(person_id, created_at)
end

Refer to the ActiveRecord documentation for more details.

If you want to do most of the calculations in the DB, try this:

OrderState.find_by_sql("SELECT A.* FROM order_states A,
                (SELECT person_id, MAX(BA.created_at) AS created_at 
                 FROM order_states BA 
                 GROUP BY BA.person_id
                 ) AS B
WHERE  A.person_id = B.person_id AND 
       A.created_at = B.created_at")

In both approaches you should index created_at column. If you have millions of users this is not a good strategy. You should store the last state in the Person table.

KandadaBoggu