【问题标题】:Postgres: difference between two timestamps (hours:minutes:seconds)Postgres:两个时间戳之间的差异(小时:分钟:秒)
【发布时间】:2017-06-23 16:43:25
【问题描述】:

我正在创建一个计算两个时间戳之间差异的选择

这里是代码:(您不必了解下面的表格。只需按照线程)

  (select value from demo.data where id=q.id and key='timestampend')::timestamp 
- (select value from demo.data where id=q.id and key='timestampstart')::timestamp) as durata

看看这个例子,如果你想更简单:

select timestamp_end::timestamp - timestamp_start as duration

结果如下:

// “durata”是持续时间

问题是第一个时间戳是 2017-06-21,第二个是 2017-06-22,所以我们有 1 天和几个小时的差异。 我该如何做才能显示结果不是像“1 天 02:06:41.993657”而是“26:06:41.993657”而不是毫秒(26:06:41)?



更新 我正在测试这个查询:

select id as ticketid,
(select value from demo.data where id=q.id and key = 'timestampstart')::timestamp as TEnd,
(select value from demo.data where id=q.id and key = 'timestampend')::timestamp as TStart,
(select
make_interval
(
0,0,0,0, -- years, months, weeks, days
extract(days from duration1)::int * 24 + extract(hours from duration1)::int, -- calculated hours (days * 24 + hours)
extract(mins from duration1)::int, -- minutes
floor(extract(secs from duration1))::int -- seconds, without miliseconds, thus FLOOR()
) as duration1
from
(
(select value from demo.data where id=q.id and key='timestampstart')::timestamp - (select value from demo.data where id=q.id and key='timestampend')::timestamp
) t(duration) as dur
from (select distinct id from demo.data) q

错误相同:[Err] ERROR: "::" 处或附近的语法错误 id = q.id 有错误

数据表是这样的:

【问题讨论】:

    标签: postgresql date-difference


    【解决方案1】:

    您可以使用EXTRACT 函数并用MAKE_INTERVAL 和一些数学方法将其包裹起来。这很简单,因为您将时间戳的每个部分都传递给它:

    select 
      make_interval(
        0,0,0,0, -- years, months, weeks, days
        extract(days from durdata)::int * 24 + extract(hours from durdata)::int, -- calculated hours (days * 24 + hours)
        extract(mins from durdata)::int, -- minutes
        floor(extract(secs from durdata))::int -- seconds, without miliseconds, thus FLOOR()
        ) as durdata
    from (
      select '2017-06-22 02:06:41.993657'::timestamp - '2017-06-21'::timestamp
      ) t(durdata);
    

    输出:

     durdata
    ----------
     26:06:41
    

    您可以将其封装在一个函数中以使其易于使用。 不用担心 timestamp - timestamp 返回的输出精度超过天数,从而丢失一些信息,因为即使不同年份的计算仍会返回天数和额外的时间部分。

    例子:

    postgres=# select ('2019-06-22 01:03:05.993657'::timestamp - '2017-06-21'::timestamp) as durdata;
            durdata
    ------------------------
     731 days 01:03:05.993657
    

    【讨论】:

    • 您的代码正在使用手动时间戳,但如果我使用 db 列,我会发现此错误:ERROR: syntax error at or near "::" 这里代码:@987654327 @demo.data是json表格式,有“id”、“key”和“value”
    • 你需要检查它返回了什么“值”。
    • 为您的预期输出附加示例数据。
    【解决方案2】:

    在 Postgres 中,虽然间隔数据类型允许小时值大于 23(请参阅 https://www.postgresql.org/docs/9.6/static/functions-formatting.html),但 to_char() 函数将删除天数,并且如果您将 delta 值放入它并且只需要“一天中的小时数”并且尝试获取 'HH24' 值。

    所以,我最终得到了这样的技巧,将 to_char(...) 与 extract('epoch' from...) 结合起来,然后将连接的值放入另一个 to_char():

    with timestamps(ts1, ts2) as (
      select
        '2017-06-21'::timestamptz,
        '2017-06-22 01:03:05.1212'::timestamptz
    ), res as (
      select
        round(extract('epoch' from ts2 - ts1) / 3600) as hours,
        to_char(ts2 - ts1, 'MI:SS') as min_sec
      from timestamps
    )
    select hours, min_sec, to_char(format('%s:%s', hours, min_sec)::interval, 'HH24:MI:SS')
    from res;
    

    结果是:

     hours | min_sec | to_char
    -------+---------+----------
        25 | 03:05   | 25:03:05
    (1 row)
    

    您可以定义一个 SQL 函数以使其更易于使用:

    create or replace function extract_hhmmss(timestamptz, timestamptz) returns interval as $$
      with delta(i) as (
        select
          case when $2 > $1 then $2 - $1
          else $1 - $2
          end
      ), res as (
        select
          round(extract('epoch' from i) / 3600) as hours,
          to_char(i, 'MI:SS') as min_sec
        from delta
      )
      select
        (
          case when $2 < $1 then '-' else '' end
          || to_char(format('%s:%s', hours, min_sec)::interval, 'HH24:MI:SS')
        )::interval
      from res;
    $$ language sql stable;
    

    使用示例:

    [local]:5432 nikolay@test=# select extract_hhmmss('2017-06-21'::timestamptz, '2017-06-22 01:03:05.1212'::timestamptz);
     extract_hhmmss
    ----------------
     25:03:05
    (1 row)
    
    Time: 0.882 ms
    [local]:5432 nikolay@test=# select extract_hhmmss('2017-06-22 01:03:05.1212'::timestamptz, '2017-06-21'::timestamptz);
     extract_hhmmss
    ----------------
     -25:03:05
    (1 row)
    

    请注意,如果时间戳以相反的顺序提供,则会出错,但修复起来并不难。 // 更新:已经修复。

    【讨论】:

      猜你喜欢
      • 2020-11-25
      • 2021-05-14
      • 1970-01-01
      • 2020-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多