2015-06-12 58 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);