Я хочу реализовать этот запрос с помощью jooq:
SELECT bank_id, array_agg(id)
FROM aggregative_line_item
GROUP BY bank_id
ORDER BY sum(amount) desc;
Теперь jooq предоставляет функцию fetchGroups(), которая идеально сопоставляет значения с Map<String, List>.
create.selectFrom(aggregative_line_item)
.fetchGroups(aggregative_line_item.bank_id, aggregative_line_item.id);
Однако я не понимаю, как упорядочить возвращаемые результаты по значению sum().
Когда вы используете ResultQuery.fetchGroups(), вы группируете наборы результатов в Java, а не в SQL. Для этого есть много законных случаев, но в вашем случае, я думаю, вы должны делать все напрямую в SQL, предполагая, что вы используете PostgreSQL, потому что вы уже использовали ARRAY_AGG()
в своем SQL-запросе. Просто пиши:
Result<Record2<String, Integer[]>> result =
create.select(AGGREGATIVE_LINE_ITEM.BANK_ID, arrayAgg(AGGREGATIVE_LINE_ITEM.ID))
.from(AGGREGATIVE_LINE_ITEM)
.groupBy(AGGREGATIVE_LINE_ITEM.BANK_ID)
.orderBy(sum(AGGREGATIVE_LINE_ITEM.AMOUNT).desc())
.fetch();
Это предполагает обычный статический импорт, в том числе:
import static org.jooq.impl.DSL.*;
Результат не совсем в той форме, которую вы искали, но вы все равно можете вызвать fetchMap()
результат, например.
Map<String, Integer[]> map = result.fetchMap(
AGGREGATIVE_LINE_ITEM.BANK_ID,
arrayAgg(AGGREGATIVE_LINE_ITEM.ID)
);
Или вместо того, чтобы повторять выражения, вы можете присвоить их локальным переменным и использовать повторно:
Field<String> key = AGGREGATIVE_LINE_ITEM.BANK_ID;
Field<Integer[]> value = arrayAgg(AGGREGATIVE_LINE_ITEM.ID);
// And then:
Map<String, Integer[]> map =
create.select(key, value)
.from(AGGREGATIVE_LINE_ITEM)
.groupBy(AGGREGATIVE_LINE_ITEM.BANK_ID)
.orderBy(sum(AGGREGATIVE_LINE_ITEM.AMOUNT).desc())
.fetchMap(key, value);
Тем не менее, если вы предпочитаете тип List<Integer>
типу Integer[]
, вместо этого вы можете использовать API JDK Collector
в ResultQuery.collect():
Map<String, List<Integer>> map =
create.select(AGGREGATIVE_LINE_ITEM.BANK_ID, arrayAgg(AGGREGATIVE_LINE_ITEM.ID))
.from(AGGREGATIVE_LINE_ITEM)
.groupBy(AGGREGATIVE_LINE_ITEM.BANK_ID)
.orderBy(sum(AGGREGATIVE_LINE_ITEM.AMOUNT).desc())
.collect(Collectors.toMap(
r -> r.value1(),
r -> Arrays.asList(r.value2())
));
@AmitGoldstein: имеет смысл. Где-то это задокументировано, а где-то нет. Хотя мы не гарантируем реализацию LinkedHashMap
, мы, безусловно, можем гарантировать стабильность порядка итераций (что и делает LinkedHashMap
). Мы улучшим это в ближайшем будущем: github.com/jOOQ/jOOQ/issues/11154
Стоит отметить, что Result#intoGroup() в настоящее время реализован с использованием LinkedHashMap, что гарантирует сохранение исходного порядка (конечно, это недокументированная деталь реализации, которая может измениться).