NHibernate聚合子查询

时间:2009-11-04 23:11:42

标签: c# .net sql-server nhibernate

我对NHibernate有一个问题,我似乎无法找到一个简单的方法。

我有以下数据库:

游戏:ID,分数,Match_ID

匹配: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,但似乎只是绕圈子。

2 个答案:

答案 0 :(得分: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>();

希望这会有所帮助..

更新:对于Criteria世界,可能会有更好的结果转换,但这只是有效:)

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"];

答案 1 :(得分: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

group by在Criteria / HQL中总是很棘手:因为group by子句只能返回任何其他列的分组列和聚合。因此,不可能从group by子句返回整个实体,只能返回您正在分组和聚合的ID。

出于这个原因,我通常使用本机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();