Как получить первый результат от группы (Jooq) - PullRequest
1 голос
/ 07 мая 2020

Мое требование - взять список идентификаторов, каждый из которых может относиться к нескольким записям, и вернуть самую новую запись для каждого идентификатора.

Казалось бы, это можно сделать с помощью комбинации orderBy(date, desc) и fetchGroups() в столбце идентификатора. Затем я использую values() для получения объектов результата.

На этом этапе мне нужно первое значение в каждом объекте результата. Я могу набрать get(0), чтобы получить первое значение в списке, но это похоже на обман. Есть ли лучший способ получить этот первый результат от объекта Result?

1 Ответ

2 голосов
/ 07 мая 2020

Вы собираетесь написать запрос топ-1 по категории, который является частным случаем запроса топ-n по категории . Большинство синтаксисов, которые вызывают такое поведение в SQL, также поддерживаются jOOQ. Вы не должны использовать группировку в клиенте, потому что вы передадите все лишние данные с сервера на клиент, что соответствует оставшимся результатам для каждой группы.

Некоторые примеры:

Стандартный SQL (когда поддерживаются оконные функции)

Field<Integer> rn = rowNumber().over(T.DATE.desc()).as("rn");

var subquery = table(
    select(T.fields())
   .select(rn)
   .from(T)
).as("subquery");

var results = 
ctx.select(subquery.fields(T.fields())
   .from(subquery)
   .where(subquery.field(rn).eq(1))
   .fetch();

Teradata и H2 ( мы можем подражать этому скоро )

var results = 
ctx.select(T.fields())
   .from(T)
   .qualify(rowNumber().over(T.DATE.desc()).eq(1))
   .fetch();

PostgreSQL

var results = 
ctx.select(T.fields())
   .distinctOn(T.DATE)
   .from(T)
   .orderBy(T.DATE.desc())
   .fetch();

Oracle

var results = 
ctx.select(
      T.DATE, 
      max(T.COL1).keepDenseRankFirstOrderBy(T.DATE.desc()).as(T.COL1),
      max(T.COL2).keepDenseRankFirstOrderBy(T.DATE.desc()).as(T.COL2),
      ...
      max(T.COLN).keepDenseRankFirstOrderBy(T.DATE.desc()).as(T.COLN))
   .from(T)
   .groupBy(T.DATE)
   .fetch();
...