6

我正在尝试使用 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

非常感谢您的建议!

4

2 回答 2

6

我不知道我是否应该将此作为新答案发布或将其添加为对原始问题的评论,但我认为我已在此线程中解决了类似的问题:

使用 Criteeria API 在 NHibernate 中选择子查询

于 2011-07-01T15:59:00.503 回答
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 问题,并且在选择中不包括按列分组。目前,使用 Criteria API 似乎根本无法实现您想要的。

按属性分组而不将其添加到选择子句

更新 使用 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)
)
于 2011-06-30T08:56:05.943 回答