2015-12-02 8 views
6

Ich versuche, eine Abfrage in QueryDSL zu schreiben, um die ältesten Elemente einer Tabelle nach ihrer ParentId gruppiert abzurufen.QueryDSL und SubQuery mit Tuple-Bedingung

Die SQL-Äquivalent sein sollte:

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 
    ) 

Jetzt in QueryDSL ich mit der Syntax bin stecken.

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

Wie schreiben Sie diese Abfrage mit einer Unterabfrage?

Die Tabellen suchen wie folgt aus:

___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  | *

Was ich bisher versucht:

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

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

und viele Syntaxfehler ...

Ich benutze eine dreckige Schleife, für den Moment, da ich noch keine Lösung gefunden habe.

+0

Gibt es eindeutige Schlüssel in der untergeordneten Tabelle? –

+0

Ja, child.id und parent.parentId sind die jeweiligen Primärschlüssel. (Vielen Dank für die Zeit zu beantworten :)) –

Antwort

1

In JPA können Unterabfragen nur im where-Teil erscheinen.

Hier ist mein nehmen auf Ihre Anfrage

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

Danke für die Antwort. Diese Abfrage funktioniert nicht, wenn Revisionsnummern identisch sind. Child.revision ist nicht eindeutig. In meiner Abfrage gibt es kein "child2", nur ein Elternteil und seine Kinder. Aus diesem Grund muss ich das Tupel, beide Werte von ParentId und Revision im Join-On-Teil der Abfrage übereinstimmen. –

+0

Ok, ist Kind-Revision einzigartig im Bereich eines Elternteils? Wenn nicht, dann gibt dies tatsächlich mehrere Zeilen pro Elternteil zurück. –

+0

Ich habe ein Beispiel für die Daten in der Frage hinzugefügt. –

1

Sie Expressions.list() verwenden können mehr als eine Spalte für die in Klausel angeben:

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

Die Alternative zu verwenden innerJoin() ist, wie in Ihrem ursprüngliche SQL.