You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JOOQ的listAgg函数中使用distinct关键字适配Oracle语法

解决方案

方案1:使用高版本JOOQ原生API(推荐)

JOOQ 3.15及以上版本已经正式开放了LISTAGG的distinct支持,提供了listAggDistinct()方法直接生成带DISTINCT关键字的聚合语句,不需要访问内部私有类。
代码示例:

create.selectDistinct(DATA.asterisk(), 
        listAggDistinct(ORGANISATIONS.LABEL, ", ")
            .withinGroupOrderBy(DATA.ID)
            .as("ORG_LABELS"))
    .from(DATA)
    .join(ORGANISATIONS).on(DATA.ORG_ID.eq(ORGANISATIONS.ID))
    .groupBy(DATA.fields())
    .fetch();

方案2:低版本JOOQ使用纯SQL片段实现

如果使用的JOOQ版本低于3.15,最稳妥的方式是通过DSL.field()构造自定义SQL片段,避免依赖JOOQ内部非公开API,兼容性最好。
代码示例:

// 构造带DISTINCT的LISTAGG聚合函数片段
Field<String> orgLabels = DSL.field(
    "LISTAGG(DISTINCT {0}, ', ') WITHIN GROUP (ORDER BY {1})",
    String.class,
    ORGANISATIONS.LABEL,
    DATA.ID
).as("ORG_LABELS");

create.selectDistinct(DATA.asterisk(), orgLabels)
    .from(DATA)
    .join(ORGANISATIONS).on(DATA.ORG_ID.eq(ORGANISATIONS.ID))
    .groupBy(DATA.fields())
    .fetch();

方案3:逻辑层先去重再聚合

如果不想写任何原生SQL片段,可以先通过子查询提前对关联的ORGANISATIONS数据去重,再执行聚合,逻辑上和带DISTINCT的LISTAGG效果一致:
代码示例:

// 先构造去重后的关联数据子查询
Table<?> subQuery = create.select(DATA.fields())
        .select(ORGANISATIONS.LABEL)
        .from(DATA)
        .join(ORGANISATIONS).on(DATA.ORG_ID.eq(ORGANISATIONS.ID))
        .distinct()
        .as("t");

// 基于子查询做聚合,此时不需要DISTINCT也能达到去重效果
create.select(subQuery.fields(DATA.fields()))
        .select(listAgg(subQuery.field(ORGANISATIONS.LABEL), ", ")
            .withinGroupOrderBy(subQuery.field(DATA.ID))
            .as("ORG_LABELS"))
    .from(subQuery)
    .groupBy(subQuery.fields(DATA.fields()))
    .fetch();

注意:不建议通过反射修改JOOQ内部ListAgg对象的私有标识位,这种方式依赖内部实现,JOOQ版本升级后很容易出现兼容性问题。

内容的提问来源于stack exchange,提问作者Remo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 11:54:03