2015-12-02 2 views
6

Я пытаюсь написать запрос в QueryDSL для извлечения самых старых элементов таблицы, сгруппированных по их parentId.QueryDSL и SubQuery с условием Tuple

SQL-эквивалент должен быть:

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 
    ) 

Сейчас в QueryDSL я застрял с синтаксисом.

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

Как вы пишете этот запрос, используя подзапрос?

Таблицы вида:

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

То, что я пытался до сих пор:

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

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

и многие синтаксические ошибки ...

Я использую на данный момент, поскольку я еще не нашел решение.

+0

Есть ли уникальные ключи в детском столе? –

+0

Да, child.id и parent.parentId являются соответствующими первичными ключами. (спасибо большое за то, что нашли время ответить :)) –

ответ

1

В подзапросах JPA могут отображаться только в той части.

Вот мое взятие на запросе

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

Спасибо за ответ. Этот запрос не работает, если номера версий идентичны. Child.revision не уникален. В моем запросе нет «child2», только родитель и его дети. Вот почему мне нужно сопоставить кортеж, оба значения parentId и ревизии в разделе «Присоединиться к части» запроса –

+0

Хорошо, является ли дочерняя ревизия уникальной в области родителя? Если нет, то это действительно вернет несколько строк на родителя. –

+0

Я добавил пример данных в вопрос. –

1

Вы можете использовать Expressions.list() указать более одного столбца для в разделе:

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

Альтернативой является использование innerJoin(), как в вашей исходный SQL.