【问题标题】:postgresql date_trunc to arbitrary precision?postgresql date_trunc 到任意精度?
【发布时间】:2014-09-08 04:52:58
【问题描述】:

postgresql 有 date_trunc 可以将时间戳值截断为特定单位,例如 hourminute。我想知道是否有任何内置函数可以让我截断到 10 分钟

我知道一个技巧是将时间戳转换为纪元,做一些数学运算,然后再转换回来。但我不喜欢它。

【问题讨论】:

标签: postgresql


【解决方案1】:

Postgres 14 date_bin.
示例使用

SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01');
Result: 2020-02-11 15:30:00

timescaleDb 扩展有一个time_bucket 函数,支持天、分钟和更低的时间间隔。
注意:目前不支持月、年:见#414

【讨论】:

    【解决方案2】:

    没有你想要的功能,但正如postgresql wiki所说,你可以自己定义功能:

    CREATE OR REPLACE FUNCTION round_time_10m(TIMESTAMP WITH TIME ZONE) 
    RETURNS TIMESTAMP WITH TIME ZONE AS $$ 
      SELECT date_trunc('hour', $1) + INTERVAL '10 min' * ROUND(date_part('minute', $1) / 10.0) 
    $$ LANGUAGE SQL;
    

    一般不超过 2 分钟:

    CREATE OR REPLACE FUNCTION round_time_nm(TIMESTAMP WITH TIME ZONE, INTEGER) 
    RETURNS TIMESTAMP WITH TIME ZONE AS $$ 
      SELECT date_trunc('hour', $1) + ($2 || ' min')::INTERVAL * ROUND(date_part('minute', $1) / $2) 
    $$ LANGUAGE SQL;
    

    【讨论】:

    • @alex-dvortsky 非常感谢。你能帮我想出一个我可以使用 n 作为汇总单位的解决方案吗?说interval 'n min'
    • 需要快速更新:第二个函数的原型错误:CREATE OR REPLACE FUNCTION round_time_nm(TIMESTAMP WITH TIME ZONE, INTEGER) 会更准确(编辑名称,添加缺少的第二个参数)
    • 谢谢。修复函数签名
    • 第二个功能似乎不起作用:jasen=# select round_time_nm(now(),10); -[ RECORD 1 ]-+----------------------- round_time_nm | 2019-03-17 23:02:00+00
    • @Jasen 你是对的。修复了功能。谢谢指点
    【解决方案3】:

    这是 date_trunc 的改进版本

    create cast (bigint as timestamptz) WITHOUT FUNCTION;
    create cast (timestamptz as bigint) WITHOUT FUNCTION;
    CREATE OR REPLACE FUNCTION date_trunc_by_interval( interval, timestamptz )
        RETURNS timestamptz 
        LANGUAGE SQL
        IMMUTABLE
        RETURNS NULL ON NULL INPUT
        AS $$ 
        select
            case when $2::bigint >= 0::bigint then
                $2::bigint - $2::bigint % (extract (epoch from $1)*1000000 ) ::bigint 
            else
                $2::bigint - $2::bigint % (extract (epoch from $1)*1000000 ) ::bigint 
                - (extract (epoch from $1)*1000000 ) ::bigint
            end ::timestamptz
    $$;
    

    这允许四舍五入到任何固定长度的间隔,例如:“864 秒”(将天分成 100 个部分)或“14 天”将日历分成两周。基础是 '2000-01-01 00:00:00.0 +00' 这是用于计算 postgres 的时期 时间戳值。

    它的工作原理是将 timestamptz 值和间隔强制转换为 bigint,并对它们进行整数运算,然后将它们强制返回时间戳

    负输入需要特殊处理(case 语句),因为 % 会导致舍入为零。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 2014-11-01
      • 2014-04-25
      • 1970-01-01
      相关资源
      最近更新 更多