2015-06-12 113 views
8

如何使用窗口函數編寫查詢並選擇QueryDSL中的所有字段? 在文檔有這樣一個例子:QueryDSL窗口函數

query.from(employee) 
.list(SQLExpressions.rowNumber() 
    .over() 
    .partitionBy(employee.name) 
    .orderBy(employee.id)); 

,但我需要生成像查詢:

SELECT * FROM 
    (SELECT employee.name, employee.id, row_number() 
    over(partition BY employee.name 
    ORDER BY employee.id) 
    FROM employee) AS sub 
WHERE row_number = 1 

,並有可能與JPAQuery辦呢?

回答

8

JPAQuery只支持JPQL的表現力,使窗口的功能,不支持,但分頁應該工作使用

query.from(employee).orderBy(employee.id).limit(1) 

如果你需要使用窗口功能,你需要employee.name和employee.id出這應該工作

NumberExpression<Long> rowNumber = SQLExpressions.rowNumber() 
    .over() 
    .partitionBy(employee.name) 
    .orderBy(employee.id).as("rowNumber"); 

query.select(employee.name, employee.id) 
    .from(SQLExpressions.select(employee.name, employee.id, rowNumber) 
         .from(employee).as(employee)) 
    .where(Expressions.numberPath(Long.class, "rowNumber").eq(1L)) 
    .fetch(); 
+0

而如何用SQLQuery做到這一點? – matteobarbieri

+0

對於SQLQuery,最好也這樣做,因爲限制/偏移量處理內部映射到由SQL引擎提供的分頁功能。 –

+1

好的謝謝。實際上,在我的代碼中,我需要排名而不是排名,所以限制是行不通的。有沒有辦法產生一個像我發佈的查詢? – matteobarbieri

0

至於寫不被支持JPQL @timo窗口函數(秩,ROW_NUMBER)(JPA 2.1版本),因此通過JPAQuery(QueryDsl JPA 4.1.4)。

但是,您可以重寫查詢,這樣是不使用等級超過():

select a.* from employees a 
where 
(
    select count(*) from employees b 
    where 
     a.department = b.department and 
     a.salary <= b.salary 
) <= 10 
order by salary DESC 

這是由JPAQuery支持,它可能是這樣的。

final BooleanBuilder rankFilterBuilder = 
    new BooleanBuilder(employee.department.eq(employee2.department)); 
rankFilterBuilder.and(employee.salary.loe(employee2.salary)); 

query.from(employee) 
.where(JPAExpressions.selectFrom(employee2) 
      .where(rankFilterBuilder) 
      .select(employee2.count()) 
      .loe(10)) 
.orderBy(employee.salary);