NHibernate Aggregate Subquery
我对 NHibernate 有一个问题,我似乎无法找到简单的解决方法。
我有以下数据库:
游戏:ID、分数、Match_ID
匹配:ID
一场比赛由三场比赛组成。
我想知道最大匹配分数是多少,所以下面的 SQL 可以解决问题:
1 2 3 4 5 | 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,所以我似乎无法弄清楚。我基本上有以下几点:
1 2 3 4 | Session.CreateCriteria<Game>() .SetProjection(Projections.ProjectionList() .Add(Projections.GroupProperty("Match")) .Add(Projections.Sum("Score"))).List(); |
在那之后,我玩弄了各种各样的 DetachedCriteria,但似乎只是在兜圈子。
对于 HQL 世界,一个查询就可以解决问题...
1 2 3 4 5 6 | 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 世界,可能会有更好的结果转换,但这很有效 :)
1 2 3 4 5 6 7 8 | 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"]; |
我实际上会在 SQL 中这样做:
1 2 3 4 | 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 对查询进行分组:
1 2 3 4 5 | 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(); |