r937 from Sitepoint was kind enough to help me figure out the query I need to return correct results from my database.
What I need is to be able to use this query as a scope and to be able to chain other scopes onto this one.
The query is:
SELECT coasters.*
FROM (
SELECT order_ridden,
MAX(version) AS max_version
FROM coasters
GROUP BY order_ridden
) AS m
INNER JOIN coasters
ON coasters.order_ridden = m.order_ridden
AND COALESCE(coasters.version,0) = COALESCE(m.max_version,0)
I tried making a scope like so:
scope :uniques, lambda {
find_by_sql('SELECT coasters.*
FROM (
SELECT order_ridden,
MAX(version) AS max_version
FROM coasters
GROUP BY order_ridden
) AS m
INNER JOIN coasters
ON coasters.order_ridden = m.order_ridden
AND COALESCE(coasters.version,0) = COALESCE(m.max_version,0)')
}
But when I tried chaining another one of my scopes onto it, it failed. Is there a way I can run this query like a normal scope?
find_by_sql
returns an Array
. But you need an ActiveRecord::Relation
to chain additional scopes.
One way to rewrite your query using ActiveRecord methods that will return an ActiveRecord::Relation
would be to rearrange it a little bit so that the nesting happens in the INNER JOIN
portion.
You may want to try something like:
scope :uniques, lambda {
max_rows = select("order_ridden, MAX(version) AS max_version").group(:order_ridden)
joins("INNER JOIN (#{max_rows.to_sql}) AS m
ON coasters.order_ridden = m.order_ridden
AND COALESCE(coasters.version,0) = COALESCE(m.max_version,0)")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With