跳到主要内容

聚合和分组

聚合

BookTable table = Tables.BOOK_TABLE;

long count = sqlClient
.createQuery(table)
.where(table.name().ilike("graphql"))
.select(
table
.asTableEx().authors().id()
.count(true) // distinct: true
)
.fetchOne();

生成的SQL为

select
// highlight-next-line
count(distinct tb_2_.AUTHOR_ID)
from BOOK tb_1_
inner join BOOK_AUTHOR_MAPPING tb_2_
on tb_1_.ID = tb_2_.BOOK_ID
where
lower(tb_1_.NAME) like ? /* %graphq% */

分组

BookTable table = Tables.BOOK_TABLE;

List<Tuple2<Long, BigDecimal>> tuples = sqlClient
.createQuery(table)
.groupBy(table.storeId())
.select(
table.storeId(),
table.price().avg()
)
.execute();
  • ❶ 按照BOOK表的外键STORE_ID分组

    信息

    这里,Jimmer不会把table.store视为表连接操作,而是整体视table.store.id为外键字段

    请参见幻连接

  • ❷ 分组列可以被直接查询

  • ❸ 非分组列不能直接查询,只能作为聚合函数表达式的参数查询

    警告

    Kotlin代码多调用了个函数:asNonNull()

    在Jimmer的Kotlin DSL中,聚合函数avg (以及summinmax) 返回类型都是Nullable的。在不使用分组的前提下,对没有数据的表的任何列进行聚合运算都会得到null。

    然而,和分组配合使用后不再如此。分组后,每一组内部至少有一条数据,如果被聚合的原始字段本身非null,则聚合后的结果不会为null。

    所以,这里通过asNonNull()将Nullable表达式转换为NonNull表达式,最终execute()函数查询到的数据类型是List<Tuple2<Long, BigDecimal>>,和第一行明确指定变量tuples的类型相同。

    如果去掉这里的asNonNull()execute()函数查询到的数据类型是List<Tuple2<Long, BigDecimal?>>,从而导致编译错误。