I am trying to write a query in QueryDSL to fetch the oldest elements of a table grouped by their parentId.
The SQL equivalent should be:
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
)
Now in QueryDSL I'm stuck with the syntax.
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.???))));
How do you write this query using a subquery ?
The tables are looking like this :
___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 | *
What I've tried so far :
.where(JPAExpressions.select(child.parent,child.revision).eq(subquery));
-> org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected end of subtree
and many syntax errors ...
I use a dirty loop, for now, since I haven't found a solution yet.
You can use Expressions.list()
to specify more than one column for the in clause:
query.from(child).where(Expressions.list(child.parent, child.revision).in(subquery));
The alternative is to use innerJoin()
, as in your original SQL.
Expressions.list(ENTITY.year, ENTITY.week).in(//
Expressions.list(Expressions.constant(1029), Expressions.constant(1)),
Expressions.list(Expressions.constant(1030), Expressions.constant(1)),
Expressions.list(Expressions.constant(1031), Expressions.constant(1))
would be what you are looking for, but QueryDSL generates wrong SQL from it:
((p0_.year , p0_.week) in (1029 , 1 , (1030 , 1) , (1031 , 1)))
In JPA subqueries can appear only in the where part.
Here is my take on your query
select(child).from(child).where(child.revision.eq(
select(child2.revision.max())
.from(child2)
.where(child2.parent.eq(child.parent))
.groupBy(child2.parent))).fetch()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With