QueryDSL Window functions

前端 未结 2 421
清歌不尽
清歌不尽 2021-01-11 23:15

How can I write a query using window functions and selecting all fields in QueryDSL? In the docs there is an example like this:

query.from(employee)
.list(SQ         


        
相关标签:
2条回答
  • 2021-01-12 00:08

    JPAQuery supports only the expressivity of JPQL, so window functions are not supported, but paging should work using

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

    In case you need to use window functions and you need employee.name and employee.id out this should work

    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 讨论(0)
  • 2021-01-12 00:15

    As written by @timo Window functions (rank, row_number) are not supported by JPQL (JPA 2.1 version) and hence by JPAQuery (QueryDsl Jpa 4.1.4).

    You can however rewrite your query so that is does not use 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
    

    This is supported by JPAQuery, it probably goes like this.

    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);
    
    0 讨论(0)
提交回复
热议问题