如何使用 NHibernate 表达加入分组子查询?

发布于 2024-10-01 02:03:29 字数 704 浏览 5 评论 0原文

我试图使用 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 进行斗争,并希望在按 col1 分组时仅选择 max(id)

非常感谢您的建议!

I'm trying to express a SQL query using NHibernate's Criteria API, and I'm running into difficulty because I'm thinking in a database-centric way while NHibernate is object-centric.

SQL (works great):

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

Essentially, this is a self-join of a table against a subset of itself. I suppose I could try turning the self-join into a restriction:

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)

But I'm not sure how to express that using NHibernate either; I'm fighting with the DetachedCriteria's ProjectionList and wanting to select only max(id) while grouping by col1.

Thanks so much for your suggestions!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

心作怪 2024-10-08 02:03:30

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

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

I don't know if I should post this as a new answer or to add it as a comment on the original question, but I think I've resolved a similar problem in this thread:

Selecting on Sub Queries in NHibernate with Critieria API

断桥再见 2024-10-08 02:03:30

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
)")

我还发现这个 JIRA 问题围绕 Criteria API,并且在选择中不包括按列分组。目前看来,使用 Criteria API 根本无法实现您想要的效果。

按属性分组,而不将其添加到 select 子句

更新
使用 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)
)

AFAIK you cannot join to subqueries at all in NHibernate but you can re-organise the query to use either an EXISTS or IN clause to replicate the same functionality.

I realise the question asks for this to be done using the Criteria API but I thought I would post a HQL version which may give someone else some ideas.

var results = session.CreateQuery("from Product p where p.Id in (
    select max(p2.id)
from Product p2
group by p2.col1
)")

I also found this JIRA issue surrounding the Criteria API and not including group by columns in the select. Currently it looks like what you want cannot be achieved using the Criteria API at all.

Group By Property without adding it to the select clause

UPDATE
Using the example from Monkey Coders post looks like you can do this:

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));

Which would produce the following SQL

select *
from Product p2
where exists (
    select p.col1
    from Product p
    group by p.col1
    having p2.Id=max(p.Id)
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文