gpt4 book ai didi

hibernate - 计算 Hibernate SQLProjection 中聚合列的排名

转载 作者:行者123 更新时间:2023-12-02 02:22:18 26 4
gpt4 key购买 nike

我正在尝试编写查询以根据聚合列计算排名列。该查询是一个 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 消息“Could not execute query”。

日志显示:

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} 似乎有问题 - 可能与嵌套子查询有关 - 谁能帮忙?

谢谢。

最佳答案

HQL 不支持select 列表中的子查询,因此您有两个选择:

  • 用 SQL 编写此查询并将其作为 native query 执行
  • 像这样写

    select max(stat.powerRestarts), stat.managedObjectName 
    from IPTStatistic stat
    group by stat.managedObjectName
    order by max(stat.powerRestarts) desc

    然后可以从行号以编程方式推导出排名

更新:

这里很重要的一点是,您需要执行两次聚合(maxcount)才能计算排名,因此您需要两次查询才能完成:

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

另请注意使用 having 而不是 where,因为条件应在第一次聚合后应用。

关于hibernate - 计算 Hibernate SQLProjection 中聚合列的排名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7567808/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com