2015-06-12 16 views
8

Come posso scrivere una query utilizzando le funzioni della finestra e selezionando tutti i campi in QueryDSL? nella documentazione c'è un esempio come questo:QueryDSL Funzioni della finestra

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

ma ho bisogno di generare una query come:

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 

Ed è possibile farlo con JPAQuery?

risposta

8

JPAQuery supporta solo l'espressività del JPQL, quindi funzioni finestra non sono supportate, ma paging dovrebbe funzionare utilizzando

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

In caso di necessità di utilizzare le funzioni delle finestre ed è necessario employee.name e employee.id fuori questo dovrebbe funzionare

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

E come farlo con SQLQuery? – matteobarbieri

+0

Per SQLQuery è meglio fare lo stesso, poiché la gestione del limite/offset è mappata internamente alla funzionalità di paging fornita dal motore SQL. –

+1

Ok, grazie. In realtà nel mio codice ho bisogno di un rank e non di un rownumber, quindi il limite non funzionerà. C'è un modo per generare una query come quella che ho postato? – matteobarbieri

0

Come ha scritto @timo funzioni di finestra (di rango, row_number) non sono supportati da JPQL (JPA versione 2.1) e, quindi, di JPAQuery (QueryDsl Jpa 4.1.4).

È possibile tuttavia riscrivere la query in modo che sia non fa uso di rango sopra():

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 

Questo è supportato da JPAQuery, probabilmente va come questo.

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