如何使用 jooq 获取按聚合值排序的组
How to fetch groups ordered by aggregative value, using jooq
我想使用 jooq 实现这个查询:
SELECT bank_id, array_agg(id)
FROM aggregative_line_item
GROUP BY bank_id
ORDER BY sum(amount) desc;
现在,jooq 提供了 fetchGroups(),可以完美地将值映射到 Map
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[]
类型,您可以在 ResultQuery.collect()
上使用 JDK Collector
API,而不是:
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())
));
我想使用 jooq 实现这个查询:
SELECT bank_id, array_agg(id)
FROM aggregative_line_item
GROUP BY bank_id
ORDER BY sum(amount) desc;
现在,jooq 提供了 fetchGroups(),可以完美地将值映射到 Map
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[]
类型,您可以在 ResultQuery.collect()
上使用 JDK Collector
API,而不是:
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())
));