Как получить группы, упорядоченные по совокупному значению, с помощью jooq

Я хочу реализовать этот запрос с помощью 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().

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
1 184
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы используете 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())
      ));

Стоит отметить, что Result#intoGroup() в настоящее время реализован с использованием LinkedHashMap, что гарантирует сохранение исходного порядка (конечно, это недокументированная деталь реализации, которая может измениться).

Amit Goldstein 20.12.2020 07:26

@AmitGoldstein: имеет смысл. Где-то это задокументировано, а где-то нет. Хотя мы не гарантируем реализацию LinkedHashMap, мы, безусловно, можем гарантировать стабильность порядка итераций (что и делает LinkedHashMap). Мы улучшим это в ближайшем будущем: github.com/jOOQ/jOOQ/issues/11154

Lukas Eder 21.12.2020 10:30

Другие вопросы по теме