NHibernate HQL子查询中的SELECT TOP

6

有没有办法在子查询上使用SetMaxResult()方法?我正在编写一个查询,以返回所有属于最近订单的订单项。因此,我需要限制子查询中记录的数量。

等效的SQL语句大致如下:

SELECT i.*
FROM tbl_Orders o
JOIN tbl_OrderItems i on i.OrderId = o.Id
WHERE
o.Id in (SELECT TOP 1 o.Id FROM tbl_Orders o orderby o.Date desc)

我使用HQL是因为Criteria API不允许你投影另一个域对象(我正在查询订单但想返回订单项)

我知道HQL不接受“SELECT TOP”,但如果我使用SetMaxResult()它将应用于外部查询而不是子查询。

有什么想法吗?


NHibernate 3相关:https://dev59.com/nlrUa4cB1Zd3GeqPkHdm - Chris S
3个回答

6
从 NHibernate 3.2 开始,你可以在查询语句的结尾使用 SKIP n / TAKE n 来控制查询结果的数量。 你的查询将会是:
SELECT i.*
FROM tbl_Orders o
JOIN tbl_OrderItems i on i.OrderId = o.Id
WHERE
o.Id in (SELECT o.Id FROM tbl_Orders o orderby o.Date desc take 1)

3

只需查询订单(并使用 SetMaxResult),并执行“提取连接”以确保所选订单的所有订单项立即加载。然后,您可以访问返回的订单中的订单项目,而不会导致向数据库发送新的 SQL 语句。


我相信这种方法也应该允许您使用标准API,如果您更喜欢的话。 - Fried Hoeben
我试图避免这种情况,因为对订单项目应用了进一步的WHERE子句,为简洁起见,我忽略了它。 那么你的意思是无法在子查询上应用限制吗? - Andy
很抱歉,我不相信在子查询中设置限制是可能的。恐怕您需要两个查询(一个用于选择您想要的n个订单的ID,然后另一个在orderlines上,其中orderId在返回的ID列表中)。但是,根据您想要的顶级订单的总订单行数,我可能会在代码中执行更多操作(即获取所有顶级n个订单的订单行,并在代码中进行过滤以选择您想要的订单行)。 - Fried Hoeben
你也可以查看过滤器,可以实时使用(例如:session.Filter(order.OrderLines, "where this.amount > 2")),也可以预定义(https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/filters.html)。 - Fried Hoeben
谢谢,Fried。把它分成两部分似乎很适合我现在的工作。 - Andy

1

我也遇到了这个问题,但是使用HQL没有找到解决方案...

使用top的子查询非常好,因为这比先进行完整连接要快。当先进行完整连接时,SQL服务器首先连接表格,对所有行进行排序,然后选择前30个。使用子查询,首先取出一个表格的前30列,然后与另一个表格连接。这样会更快!

我的子查询查询大约需要1秒钟,而连接和排序的查询需要15秒钟!所以连接不是一个选项。

最终我用了两个查询,首先是子查询:

IQuery q1 = session.CreateQuery("select id from table1 order by id desc");
q1.SetMaxResults(100);

然后是第二个查询

IQuery q2 = session.CreateQuery("select colone, coltwo from table2 where table1id in (:subselect)");
q2.SetParameterList("subselect", q1.List());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接