计算 Hibernate SQLProjection 中聚合列的排名
我正在尝试编写一个查询来根据聚合列计算排名列。该查询是一个 SQLProjection,作为 Hibernate Criteria 查询的一部分。 这是我尝试过的:
String sqlProjection =
"(select count(*) from IPTStatistic stat2 where
max(s.powerRestarts) > max({alias}.powerRestarts)) as rank)";
ProjectionList list = Projections.projectionList();
list.add(Projections.sqlProjection(sqlRankQuery, new String[]{"rank"}, new Type[]{new IntegerType()})));
list.add(Property.forName("managedObjectName").group());
list.add(Projections.max("powerRestarts").as("maxRestarts"));
Criteria crit = hibernateSessionHelper.getSessionFactory().getCurrentSession().createCriteria(IPTStatistic.class);
crit.setProjection(projection);
crit.list();
当我在 SQL 投影中使用非聚合列时,子选择起作用并且我得到了预期的结果,只有当我引入 max() 发生错误。
这会抛出一个相当不具体的org.hibernate.exception.GenericJDBCException
,并带有消息“无法执行查询
”。
日志显示:
WARN logExceptions, SQL Error: -458, SQLState: S1000
ERROR logExceptions, java.lang.NullPointerException java.lang.NullPointerException
我无法从上述错误消息中找出查询中的问题,任何人都可以给我一些关于如何纠正查询的指示吗?
更新:
我现在按照 axtavt 的回答使用以下 sqlProjection:
String sqlProjection = "(select count(*) from " +
"(select name from IPTStatistic s group by s.name " +
" having max(s.powerRestarts) > max({alias}.powerRestarts)) " +
"as r) as rank"
Hibernate 生成的 SQL 是:
select (select count(*) from (select iptManagedObjectName from IPTStatistic s group by s.iptManagedObjectName having max(s.powerRestarts) > max(this_.powerRestarts)) as r) as rank, this_.iptManagedObjectName as y1_, from IPTStatistic this_
我现在收到错误:
WARN logExceptions, SQL Error: -5581, SQLState: 42581
ERROR logExceptions, unexpected token: SELECT
如果我删除 max({alias}.powerRestarts)
并将其替换为常量或 max(s.powerRestarts)
,然后查询就可以工作(但显然无法正确计算排名)。
在此 sqlProjection
查询中使用 {alias}
似乎存在问题 - 可能与嵌套子查询有关 - 有人可以帮忙吗?
谢谢。
I am trying to write a query to calculate a rank column based upon an aggregate column. The query is an SQLProjection as part of a Hibernate Criteria query. Here is what I have tried:
String sqlProjection =
"(select count(*) from IPTStatistic stat2 where
max(s.powerRestarts) > max({alias}.powerRestarts)) as rank)";
ProjectionList list = Projections.projectionList();
list.add(Projections.sqlProjection(sqlRankQuery, new String[]{"rank"}, new Type[]{new IntegerType()})));
list.add(Property.forName("managedObjectName").group());
list.add(Projections.max("powerRestarts").as("maxRestarts"));
Criteria crit = hibernateSessionHelper.getSessionFactory().getCurrentSession().createCriteria(IPTStatistic.class);
crit.setProjection(projection);
crit.list();
When I use a non-aggregate column in the SQL projection, the subselect works and I get the expected results, it is only once I introduce the max()
that the error occurs.
This throws a fairly non-specific org.hibernate.exception.GenericJDBCException
with message "Could not execute query
".
The log shows:
WARN logExceptions, SQL Error: -458, SQLState: S1000
ERROR logExceptions, java.lang.NullPointerException java.lang.NullPointerException
I can't pinpoint the problem in the query myself from the above error messages, can anyone give me some pointers on how to correct my query?
UPDATE:
I am now using the following sqlProjection as per axtavt's answer below:
String sqlProjection = "(select count(*) from " +
"(select name from IPTStatistic s group by s.name " +
" having max(s.powerRestarts) > max({alias}.powerRestarts)) " +
"as r) as rank"
The SQL generated by Hibernate is:
select (select count(*) from (select iptManagedObjectName from IPTStatistic s group by s.iptManagedObjectName having max(s.powerRestarts) > max(this_.powerRestarts)) as r) as rank, this_.iptManagedObjectName as y1_, from IPTStatistic this_
I am now getting the error:
WARN logExceptions, SQL Error: -5581, SQLState: 42581
ERROR logExceptions, unexpected token: SELECT
If I remove max({alias}.powerRestarts)
and replace it with either a constant or max(s.powerRestarts)
, then the query works (but obviously does not calculate the rank correctly).
There seems to be a problem using the {alias}
in this sqlProjection
query - possibly something to do with the nested subqueries - can anyone help?
Thankyou.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
HQL 不支持
select
列表中的子查询,因此您有两个选择:写一些类似的内容
然后可以通过编程方式从行号推导出排名
更新:
这里重要的一点是,您需要执行两个操作聚合(
max
和count
)来计算排名,因此您需要两个查询来完成此操作:另请注意
having
的使用而不是where
,因为条件应该在第一次聚合之后应用。HQL doesn't support subqueries in
select
list, thus you have two options:Write something like
then rank can be deduced programmatically from a row number
UPDATE:
An important point here is that you need to perform two aggregations (
max
andcount
) in order to calculate a rank, so that you need two queries to do it:Also note the use of
having
instead ofwhere
, since condition should be applied after the first aggregation.