jooq multiset order 结果集通过 multiset 上的条件

Posted

技术标签:

【中文标题】jooq multiset order 结果集通过 multiset 上的条件【英文标题】:jooq multiset order result set via conditions on multiset 【发布时间】:2021-12-01 18:08:37 【问题描述】:

收集第一次体验 mit jooq 的 multiset 我试图弄清楚如何根据 multiset 的一些标准对结果集进行排序。 考虑一个带有产品表的数据结构,每个产品都可以分配任意数量的存储空间。

使用此查询获取产品时:

  List<ProductFilterItem> items =
        dslContext
            .select(
                PRODUCT.ID,
                PRODUCT.NAME
                multiset(
                    select(
                        PRODUCT_STORAGE.ID,
                        PRODUCT_STORAGE.PRODUCT_ID,
                        PRODUCT_STORAGE.STOCK
                        PRODUCT_STORAGE.MIN_STOCK
                    )
                        .from(PRODUCT_STORAGE)
                        .where(PRODUCT_STORAGE.PRODUCT_ID.eq(PRODUCT.ID))
                ).as("storage").convertFrom(r -> r.into(ProductStorageItem.class))
            )
            .from(PRODUCT)
            .where(queryCondition)
            .fetchInto(ProductItem.class)

如何根据多重集的标准对结果进行排序。

例如,将那些分配了存储空间的放在第一位。

orderBy(inline(3).desc())

给出了想要的结果,但对我来说,不清楚实际的排序比较在做什么。

如何实现更复杂的排序, 例如排序方式

min(
(PRODUCT_STORAGE.STOCK - PRODUCT_STORAGE.MIN_STOCK)
  .divide(PRODUCT_STORAGE.MIN_STOCK.multiply(0.01))
)

或其他基于股票价值的计算。

感谢您的帮助!

亲切的问候, 安德烈亚斯

【问题讨论】:

【参考方案1】:

依靠MULTISET下单

从 jOOQ 3.15 开始,MULTISET 使用 SQL/XML 或 SQL/JSON 在所有方言中进行模拟。虽然 XML 文档的顺序是未定义的,但某些 SQL 方言可能会选择在 JSON 文档上定义顺序(例如 PostgreSQL 为JSONB 这样做)。但我不相信在你的情况下依赖这种隐式排序是一个好主意(特别是因为 jOOQ 的模拟可能会微妙地改变以适应某些边缘情况),所以最好明确你想要什么。

在标准 SQL 中,您可以再次从您的 MULTISET 嵌套集合中提取数据,以便找到像您的 MIN(...) 表达式这样的聚合值,但这似乎很费力,目前 jOOQ 3.15 不支持(有一些标准的 SQL 操作符来操作多重集,参见https://github.com/jOOQ/jOOQ/issues/12031)

MULTISET_AGG替代

既然您想按某个汇总值排序,为什么不使用MULTISET_AGG 而不是MULTISET?在下面的例子中,你会得到一个等价的结果,并且排序是明确定义的。

List<ProductFilterItem> items = dslContext
    .select(
        PRODUCT.ID,
        PRODUCT.NAME
        multisetAgg(
            PRODUCT_STORAGE.ID,
            PRODUCT_STORAGE.PRODUCT_ID,
            PRODUCT_STORAGE.STOCK
            PRODUCT_STORAGE.MIN_STOCK
        ).as("storage").convertFrom(r -> r.into(ProductStorageItem.class))
    )
    .from(PRODUCT)
    .leftJoin(PRODUCT_STORAGE)
        .on(PRODUCT_STORAGE.PRODUCT_ID.eq(PRODUCT.ID))
    .where(queryCondition)
    .groupBy(PRODUCT.ID, PRODUCT.NAME)
    .orderBy(min(
        PRODUCT_STORAGE.STOCK
            .minus(PRODUCT_STORAGE.MIN_STOCK)
            .divide(PRODUCT_STORAGE.MIN_STOCK.multiply(0.01))
    ))
    .fetchInto(ProductItem.class)

【讨论】:

有没有办法让这种方法适用于多级嵌套集合?到目前为止,我的尝试都因“不能嵌套聚合函数调用”错误而失败。 @StevenGrimm:很难说。很乐意用一个具体的例子来回顾一个新问题。通常,有不同的方法来解决问题,例如这个问题/答案已经显示... Asked this as a new question 并从这里链接,以防有人先解决这个问题。

以上是关于jooq multiset order 结果集通过 multiset 上的条件的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式获取 jOOQ 中表的外键

JOOQ:如何使用多重集

使用 jOOQ 创建自定义聚合函数

没有 order by 子句的 Oracle 排序结果集

21《MySQL 教程》ORDER BY 排序

使用具有“order by”组件的窗口函数时,结果集的顺序是啥?