3

集計列に基づいてランク列を計算するクエリを作成しようとしています。クエリは、Hibernate Criteria クエリの一部としての SQLProjection です。これが私が試したことです:

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)、クエリは機能します(ただし、ランクが正しく計算されないことは明らかです)。


{alias}このクエリでの使用に問題があるようですsqlProjection- おそらくネストされたサブクエリと関係があります - 誰でも助けてもらえますか?

ありがとうございました。

4

1 に答える 1

2

HQL はリスト内のサブクエリをサポートしていないためselect、次の 2 つのオプションがあります。

  • このクエリを SQL で記述し、ネイティブ クエリとして実行します。
  • のようなものを書く

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

    次に、行番号からプログラムでランクを推測できます

アップデート:

ここで重要な点は、ランクを計算するには 2 つの集計 (maxおよびcount) を実行する必要があるため、2 つのクエリが必要になることです。

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

于 2011-09-27T11:32:36.267 に答える