【问题标题】:Extract date from datetime and calculate total minutes from duration从日期时间中提取日期并根据持续时间计算总分钟数
【发布时间】:2018-05-15 21:02:15
【问题描述】:

我在 Postgres 中有一张如下表:

| id | start_time               | end_time                 | duration |
|----|--------------------------|--------------------------|----------|
| 1  | 2018-05-11T00:00:20.631Z | 2018-05-11T01:03:14.496Z | 1:02:54  |
| 2  | 2018-05-11T00:00:04.877Z | 2018-05-11T00:00:14.641Z | 0:00:10  |
| 3  | 2018-05-11T01:03:28.063Z | 2018-05-11T01:04:36.410Z | 0:01:08  |
| 4  | 2018-05-11T00:00:20.631Z | 2018-05-11T02:03:14.496Z | 2:02:54  |

start_timeend_time 存储为 varchar。格式为'yyyy-mm-dd hh24:mi:ss.ms'(ISO 格式)。
duration 已计算为end_time - start_time。格式为hh:mi:ss

我需要结果表输出如下:

| id | start_time               | end_time                 | duration | start     | end       | duration_minutes |
|----|--------------------------|--------------------------|----------|-----------|-----------|------------------|
| 1  | 2018-05-11T00:00:20.631Z | 2018-05-11T01:03:14.496Z | 1:02:54  | 5/11/2018 | 5/11/2018 | 62               | -- (60+2)
| 2  | 2018-05-11T00:00:04.877Z | 2018-05-11T00:00:14.641Z | 0:00:10  | 5/11/2018 | 5/11/2018 | 0                |
| 3  | 2018-05-11T01:03:28.063Z | 2018-05-11T01:04:36.410Z | 0:01:08  | 5/11/2018 | 5/11/2018 | 1                |
| 4  | 2018-05-11T00:00:20.631Z | 2018-05-11T02:03:14.496Z | 2:02:54  | 5/11/2018 | 5/11/2018 | 122              | -- (2X60 +2)

startend 只需分别包含start_timeend_timemm/dd/yyyy 部分。

duration_minutes 应以分钟为单位计算总持续时间(例如,如果持续时间为 1:02:54,则持续时间以分钟为单位应为 62,即 60+2)

如何使用 SQL 来做到这一点?

【问题讨论】:

  • 使用适当的数据类型。 varchar 在这里不合适。
  • 到底为什么要将时间戳存储为 varchar?这是一个非常糟糕的主意
  • @a_horse_with_no_name :我将其存储为日期时间
  • Postgres 中没有datetimetimestamptimestamptzstackoverflow.com/a/9576170/939860。而duration 可能应该是类型interval。我们应该继续假设varchar 输入还是timestamp / interval?您的结果中是否需要 TZ 装饰器?这些在 ISO 格式中是可选的。

标签: sql postgresql datetime


【解决方案1】:

基于varchar 输入,此查询会产生您想要的结果,确切地说:

SELECT *
     , to_char(start_time::timestamp, 'FMMM/DD/YYYY') AS start
     , to_char(end_time::timestamp, 'FMMM/DD/YYYY') AS end
     , extract(epoch FROM duration::interval)::int / 60 AS duration_minutes
FROM   tbl;

要点:

  • 首先使用timestampinterval 而不是varchar
    或者根本不存储功能依赖列duration。它可以廉价地即时计算。

  • 对于显示 / 特定的文本表示,请使用to_char()
    明确,不要依赖可能因会话而异的区域设置。
    FM 模式修饰符用于 (quoting the manual):

    填充模式(抑制前导零和填充空白)

  • extract (epoch FROM interval_tpe) 产生包含的秒数。你想截断小数分钟吗?整数除法就是这样做的,所以像演示的那样转换为int。相关:

【讨论】:

  • @Erwin Brandstetter :我使用了extract(epoch FROM duration::interval)::int AS duration_seconds 并获得了秒数。但是我怎样才能捕捉到毫秒数
  • @Symphony:转换为整数 rounds 小数秒。放弃演员以获得最多 6 个小数位数的 double precision 号码:extract(epoch FROM duration::interval) AS seconds_with_fractions。但是您在示例中的持续时间已经四舍五入,因此您需要重新计算持续时间以获得小数单位。参见:dbfiddle here
【解决方案2】:

以下似乎可以满足您的要求:

select v.starttime::timestamp::date, v.endtime::date,
       extract(epoch from v.endtime::timestamp - v.starttime::timestamp)/60
from (values ('2018-05-11T00:00:20.631Z', '2018-05-11T01:03:14.496Z')) v(starttime, endtime)

如果您想要特定格式的日期,请使用to_char()

【讨论】:

  • 我不想重新计算持续时间。我只想把它转换成分钟
猜你喜欢
  • 1970-01-01
  • 2016-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 1970-01-01
  • 2019-12-24
  • 2017-05-26
相关资源
最近更新 更多