【问题标题】:Fetching a sum of intervals in JOOQ在JOOQ中获取间隔总和
【发布时间】:2017-05-27 21:32:22
【问题描述】:

我正在寻找一种独立于方言的方法来返回两个 TIMESTAMP 字段之间的间隔持续时间之和,使用如下选择:

DSL.sum(DSL.timestampDiff(MY_TABLE.START, MY_TABLE.END))

在 JOOQ 中,sum(...) 返回一个 Field<BigDecimal>。这恰好在 HSQLDB 中起作用,因为它使用毫秒表示 INTERVAL。但是,在 PostgreSQL 中,此查询会崩溃,因为无法从本机 INTERVAL 类型自动转换为 BigDecimal。

我现在正在 JOOQ 中寻找一种跨平台的方式来将 INTERVAL 转换为(毫秒)秒,这样我就可以将这些数字相加成一个数值。

有什么建议吗? (或者也许有更优雅的方法来解决这个难题?)

【问题讨论】:

    标签: postgresql hsqldb jooq


    【解决方案1】:

    这可能是 jOOQ (#5785) 中的一个错误。

    作为一种解决方法,您可以像这样实现自己的 sum 函数:

    public static Field<BigDecimal> sumTimestampDiff(
        final Field<Timestamp> start, 
        final Field<Timestamp> end
    ) {
        return new CustomField<BigDecimal>("sum", SQLDataType.NUMERIC) {
            @Override
            public void accept(Context<?> ctx) {
                switch (ctx.family()) {
                    case HSQLDB:
                        ctx.visit(sum(timestampDiff(start, end)));
                        break;
                    case POSTGRES:
                        ctx.visit(sql("sum(1000 * extract('epoch' from ({0} - {1})))", 
                                      start, end));
                        break;
                }
            }
        };
    }
    

    我正在使用the extract() expression from Evan's answer here

    上面的代码 sn-p 假设你有这个静态导入:

    import static org.jooq.impl.DSL.*;
    

    More info about CustomField here.

    【讨论】:

    • 我不太可能在我的任何代码中这样做。我会将间隔存储为间隔,并希望返回一个间隔。或者在数据库中执行我的操作,其中间隔很重要并且处理得当。但是,我不知道他是如何使用 jooq 的。不过因为将其融入他的语言而受到支持。
    • @EvanCarroll:我知道你的意思,但如果你想成为数据库供应商不可知论者,有时,你必须解决限制/不兼容性。
    • 我确实在寻找 JOOQ 方法来以平台中立的方式处理间隔。对我来说,这包括将内联 (SQL) 转换为一定数量的已定义时间单位,还包括将间隔查询的结果作为某种间隔类型(如 Java 8 Duration)获取。 @LukasEder:感谢您将此问题注册为错误。
    • PS:建议的解决方案实际上在 HSQLDB 中返回毫秒,从 PostgreSQL 中返回秒。 (另请注意,示例代码应为SQLDataType.NUMERIC,并且在return 子句之后缺少;。) - 但我喜欢快速响应和清晰的解决方案;你拯救了我的一天!
    • @Timo:好的,修复了 ms vs seconds 问题和语法错误。不幸的是,java.time.Duration 不是一个非常适合的类型,因为它根本不对应任何 SQL 间隔类型,它只是在内部存储秒(例如,一分钟并不总是有 60 秒!)。 timestampDiff() 确实返回了与平台无关的间隔类型 (DayToSecond),但 sum() 目前无法使用它。
    【解决方案2】:

    来自the lists

    select extract ('epoch' from '5 days 5 hours'::interval);
    

    【讨论】:

    • 虽然这是正确的(也是众所周知的)PostgreSQL 解决方案,但这不是 JOOQ 语法。
    猜你喜欢
    • 1970-01-01
    • 2019-09-07
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多