2009-11-04 3 views
2

У меня проблема с NHibernate, что, похоже, я не могу найти простой способ.NHibernate Aggregate Subquery

У меня есть следующие базы данных:

игры: ID, Score, Match_ID

Match: ID

Матч состоит из 3-х игр.

Я хочу, чтобы выяснить, что максимальный балл Матч, поэтому следующий SQL будет делать трюк:

select max(a.total) from 
    (select Match.ID, sum(Game.Score) as total 
    from Game inner join Match 
    on Game.Match_ID = Match.ID 
    group by Match.ID) a 

В NHibernate, это, кажется, немного сложнее. По-видимому, HQL не разрешает подзапросы в предложении from, поэтому я не могу это использовать.

Я уверен, что это можно сделать с помощью ICriteria, но я только начал использовать NH, поэтому я не могу понять это. Я в основном получили следующее:

Session.CreateCriteria<Game>() 
    .SetProjection(Projections.ProjectionList() 
     .Add(Projections.GroupProperty("Match")) 
     .Add(Projections.Sum("Score"))).List(); 

После этого я играл с различными ассортиментов DetachedCriteria, но, похоже, просто идти по кругу.

ответ

6

Для HQL мира один запрос делает трюк ...

var maxScore = session.CreateQuery(@"select sum(game.Score) 
            from Game game 
            group by game.Match 
            order by sum(game.Score) desc") 
         .SetMaxResults(1) 
         .UniqueResult<long>(); 

Надеется, что это помогает. .

Обновление: И для мира критериев может быть лучшая трансформация результата, но это только работает :)

var max = (int)session.CreateCriteria<Game>("game") 
    .SetProjection(Projections.ProjectionList() 
         .Add(Projections.GroupProperty("game.Match")) 
         .Add(Projections.Sum("game.Score"), "total")) 
    .AddOrder(Order.Desc("total")) 
    .SetMaxResults(1) 
    .SetResultTransformer(Transformers.AliasToEntityMap) 
    .UniqueResult<IDictionary>()["total"]; 
+0

Спасибо, HQL работает. – Carl

1

Я бы на самом деле сделать это таким образом, в SQL:

select top 1 Match.ID, sum(Game.Score) as total 
    from Game inner join Match 
    on Game.Match_ID = Match.ID 
    group by Match.ID order by total desc 

группа по всегда сложно в критериях/HQL: потому, что группа по п может возвращать только сгруппированных колонку и агрегаты любого другого столбца. Поэтому невозможно вернуть целую сущность из предложения group by, только идентификатор, который вы группируете и объединяете.

По этой причине я обычно делаю группу запросов, используя нативный SQL, как это:

ISQLQuery sqlQuery1 = NHibernateSessionManager.Instance.GetSession().CreateSQLQuery("select Match.ID, sum(Game.Score) as total from Game inner join Match on Game.Match_ID = Match.ID group by match.ID order by total desc"); 
sqlQuery1.AddScalar("id", NHibernateUtil.Int32); // 
sqlQuery1.AddScalar("total", NHibernateUtil.Int32); 
sqlQuery1.SetMaxResults(1);  
var result = sqlQuery1.List(); 
+0

Я даже не думал об изменении этого запроса, спасибо! Я на самом деле «один из тех», которые ранее делали большинство вещей в качестве хранимых процедур, поэтому помещать SQL в мой код, вероятно, не произойдет. Сначала HQL напугал меня, но я думаю, что он довольно мощный, поэтому я буду идти по тому маршруту, который я думаю. – Carl

+0

Да! За исключением того, что другой парень ущипнул мой SQL и превратил его в HQL! – reach4thelasers