NHibernate Aggregate Subquery

2

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

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

Игра: 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, но, похоже, кругом крутился.

Теги:
sql-server
nhibernate

2 ответа

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 работает удовольствие.
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 может возвращать только сгруппированный столбец и агрегаты любого другого столбца. Поэтому невозможно вернуть целую сущность из предложения 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 меня напугал, но я думаю, что он довольно мощный, поэтому я пойду по этому пути, я думаю.
  • 0
    Да уж! За исключением того, что другой парень ущипнул мой SQL и превратил его в HQL!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню