2011-09-27 30 views
3

我正在嘗試編寫一個查詢來計算基於聚合列的排名列。查詢是SQLProjection作爲Hibernate Criteria查詢的一部分。 這是我曾嘗試:在Hibernate 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()的錯誤發生。

這會引發消息「Could not execute query」的非常具體的org.hibernate.exception.GenericJDBCException

日誌顯示:

WARN logExceptions, SQL Error: -458, SQLState: S1000 
ERROR logExceptions, java.lang.NullPointerException java.lang.NullPointerException 

我不能從上面的錯誤消息查明問題在查詢自己,任何人都可以給我如何糾正我的查詢一些指點?


UPDATE:

我現在用以下sqlProjection按以下axtavt的回答是:

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}一個問題 - 可能的東西與嵌套子查詢做 - 誰能幫助?

謝謝。

回答

2

HQL不支持子查詢中select列表,從而你有兩個選擇:

  • 寫這個查詢在SQL中並執行它作爲一個native query
  • 喜歡寫東西

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

    然後排名可以編程從行號推導

UPDATE:

這裏很重要的一點是,你需要爲了計算秩執行兩個聚合(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,因爲條件應該在第一次聚合後應用。

+0

Thankyou,你的回答是正確的,關於子查詢在HQL查詢select子句(+1)中被禁止,但我意識到我犯了一個錯誤 - 代碼實際上並不是HQL,它是SQLProjection作爲條件查詢,原生SQL也是如此。我已澄清並更正了該問題,請參閱編輯。 – EkcenierK

+0

@KLibby:如果是這樣,完整的標準查詢看起來如何? – axtavt

+0

我現在已經添加了我構建的Hibernate Criteria的完整代碼。 – EkcenierK