QueryDSL Window 函数

QueryDSL Window functions

如何使用 window 函数编写查询并选择 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 来实现?

JPAQuery 仅支持 JPQL 的表达能力,因此 window 函数不受支持,但分页应该可以使用

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

如果您需要使用 window 函数并且需要 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();

@timo 所写 Window 函数(等级,row_number)不受 JPQL(JPA 2.1 版本)支持,因此不受 JPAQuery( QueryDsl Jpa 4.1.4).

但是您可以重写您的查询,这样就不会使用 rank over():

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