A straightforward transliteration of your description to SQL would look like this:
select name, path, value
from (
select name, path, value,
row_number() over (partition by path order by value desc) as r
from your_table
where path is not null
) as dt
where r = 1
union all
select name, path, value
from your_table
where path is null
You could wrap that in a find_by_sql
and get your objects out the other side.
That query works like this:
- The
row_number
window function allows us to group the rows by path
, order each group by value
, and then number the rows in each group. Play around with the SQL a bit inside psql
and you'll see how this works, there are other window functions available that will allow you to do all sorts of wonderful things.
- You're treating NULL
path
values separately from non-NULL path
s, hence the path is not null
in the inner query.
- We can peel off the first row in each of the
path
groups by selecting those rows from the derived table that have a row number of one (i.e. where r = 1
).
- The treatment of
path is null
rows is easily handled by the section query.
- The UNION is used to join the result sets of the queries together.
I can't think of any way to construct such a query using ActiveRecord nor can I think of any way to integrate such a query with ActiveRecord's scope mechanism. If you could easily access just the WHERE component of an ActiveRecord::Relation
then you could augment the where path is not null
and where path is null
components of that query with the WHERE components of a scope chain. I don't know how to do that though.
In truth, I tend to abandon ActiveRecord at the drop of a hat. I find ActiveRecord to be rather cumbersome for most of the complicated things I do and not nearly as expressive as SQL. This applies to every ORM I've ever used so the problem isn't specific to ActiveRecord.