2015-12-02 29 views
6

Próbuję napisać zapytanie w QueryDSL, aby pobrać najstarsze elementy tabeli pogrupowane według ich parentId.QueryDSL i subQuery w stanie Tuple

Odpowiednik SQL powinny być:

SELECT a.* FROM child a 
    INNER JOIN 
    (
     SELECT parentId, MAX(revision) FROM child GROUP BY parentId 
    ) b 
    ON ( 
     a.parentId = b.parentId AND a.revision = b.revision 
    ) 

Teraz w QueryDSL utknąłem ze składnią.

JPQLQuery<Tuple> subquery = JPAExpressions 
       .select(child.parent, child.revision.max()) 
       .from(child) 
       .groupBy(child.parent); 

HibernateQuery<Child> query = new HibernateQuery<>(session); 
query.from(child) 
    .where(child.parent.eq(subquery.???).and(child.revision.eq(subquery.???)))); 

Jak napisać to zapytanie za pomocą podkwerendy?

tabele wyglądają tak:

___parent___ (not used in this query, but exists) 
parentId 
P1  | * 
P2  | * 
P3  | * 

___child___ 
parentId | revision 
P1  | 1  | * 
P1  | 2  | * 
P1  | 3  | * 
P2  | 2  | * 
P2  | 3  | * 
P3  | 1  | * 

___result from child, the highest revision for each parentId___ 
P1  | 3  | * 
P2  | 3  | * 
P3  | 1  | *

Co próbowałem dotąd:

.where(JPAExpressions.select(child.parent,child.revision).eq(subquery)); 

-> org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected end of subtree 

i wiele błędów składni ...

używam brudna pętla, na razie, ponieważ nie znalazłem jeszcze rozwiązania.

+0

Czy w dziecięcym stole znajdują się unikatowe klucze? –

+0

Tak, child.id i parent.parentId są odpowiednimi kluczami podstawowymi. (dziękuję bardzo za poświęcenie czasu na odpowiedź :)) –

Odpowiedz

1

W podzapytaniach JPA może pojawić się tylko w części gdzie.

Oto moje zdanie na zapytaniu

select(child).from(child).where(child.revision.eq(
    select(child2.revision.max()) 
.from(child2) 
.where(child2.parent.eq(child.parent)) 
.groupBy(child2.parent))).fetch() 
+0

Dzięki za odpowiedź. To zapytanie nie działa, gdy numery wersji są identyczne. Child.revision nie jest wyjątkowy. W moim zapytaniu nie ma "child2", tylko rodzic i jego dzieci. Właśnie dlatego muszę dopasować krotkę, obie wartości parentId i revision w części Join On zapytania –

+0

OK, czy wersja podrzędna jest unikalna w zakresie rodzica? Jeśli nie, to spowoduje to powrót wielu wierszy na rodzica. –

+0

Dodałem przykład danych w pytaniu. –

1

Można użyć Expressions.list() określić więcej niż jedną kolumnę dla w klauzuli:

query.from(child).where(Expressions.list(child.parent, child.revision).in(subquery)); 

Alternatywą jest użycie innerJoin(), jak w swojej oryginalny SQL.