I managed to solve a similar problem by slightly adapting the original SQL query. I ended up with something like this (pseudo sql code):
SELECT p.* FROM [Items] as p WHERE EXISTS ( SELECT [childId] as childNodeId FROM [Items] as q WHERE p.[childId] = q.[childNodeId] GROUP BY q.[childId] HAVING p.[price] = MAX(q.[price]) )
And this is the implementation of QueryOver:
var subquery = QueryOver.Of(() => q) .SelectList(list => list.SelectGroup(() => q.ChildId)) .Where(Restrictions.EqProperty( Projections.Property(() => p.Price), Projections.Max(() => q.Price))) .And(Restrictions.EqProperty( Projections.Property(() => p.ChildId), Projections.Property(() => q.ChildId)));
From here you only need to pass the aliases so that NHibernate can correctly resolve entities (pseudocode):
var filter = QueryOver.Of(() => p) .WithSubquery.WhereExists(GetSubQuery(p, criteria...));
Hope this helps in your specific case.
UPDATE: criteria API
var subquery = DetachedCriteria.For<Items>("q") .SetProjection(Projections.ProjectionList() .Add(Projections.GroupProperty("q.ChildId"))) .Add(Restrictions.EqProperty("p.Price", Projections.Max("q.Price"))) .Add(Restrictions.EqProperty("p.ChildId", "q.ChildId")); var query = DetachedCriteria.For<Items>("p") .Add(Subqueries.Exists(subquery));
However, I would recommend sticking with the QueryOver version, it is much more intuitive and you avoid magic lines (especially that you do not need to update the NH version).
Please let me know if this works for you.
Monkeycoder
source share