我正在尝试使用NHibernate的Criteria API来表达SQL查询,并且我遇到了困难,因为我正在考虑以数据库为中心的方式,而NHibernate是以对象为中心的。
SQL(效果很好):
select outerT.id, outerT.col1, outerT.col2, outerT.col3
from tbl outerT
inner join
(select max(innerT.id)
from tbl innerT
group by innerT.col1) grpT
on outerT.id = grpT.id
基本上,这是一个表与自身子集的自连接。我想我可以尝试将自我联接转变为限制:
select outerT.id, outerT.col1, outerT.col2, outerT.col3
from tbl outerT
where outerT.id in (select max(innerT.id) from tbl innerT group by innerT.col1)
但是我不确定如何使用NHibernate来表达它;我正在使用DetachedCriteria的ProjectionList,并希望在按max(id)
进行分组时仅选择col1
。
非常感谢您的建议!
答案 0 :(得分:6)
我不知道是否应将此作为新答案发布或将其添加为对原始问题的评论,但我认为我已在此主题中解决了类似的问题:
答案 1 :(得分:1)
AFAIK您无法在NHibernate中加入子查询,但您可以重新组织查询以使用EXISTS或IN子句来复制相同的功能。
我意识到这个问题要求使用Criteria API完成,但我想我会发布一个HQL版本,可能会给别人一些想法。
var results = session.CreateQuery("from Product p where p.Id in (
select max(p2.id)
from Product p2
group by p2.col1
)")
我还发现围绕Criteria API的这个JIRA问题,并且不包括select中的列。目前,看起来根本无法使用Criteria API实现您想要的目标。
Group By Property without adding it to the select clause
<强>更新强> 使用Monkey Coders帖子中的示例看起来就像你可以这样做:
var subquery = DetachedCriteria.For<Product>("p")
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("p.Col1"))
.Add(Restrictions.EqProperty("p2.Id", Projections.Max("p.Id"));
var query = DetachedCriteria.For<Product>("p2")
.Add(Subqueries.Exists(subquery));
哪会产生以下SQL
select *
from Product p2
where exists (
select p.col1
from Product p
group by p.col1
having p2.Id=max(p.Id)
)