【问题标题】:Extract equivalent HOUR of a Time duration提取时间持续时间的等效 HOUR
【发布时间】:2019-01-08 10:17:33
【问题描述】:

我有以下日期字段格式:“HH:MM”,表示事件的持续时间,我想提取 HOUR 中的等效值(例如:2h:30min ==> 结果:2, 5 小时)。

【问题讨论】:

  • 保持小时不变,然后将分钟除以 60。这不是你想要的吗?
  • 字段的格式是varchar,所以不能直接将分钟除以60!
  • 您应该告诉人们您使用的是分析应用程序而不是 SQL 代码! OBI 分析不能通过编写 SQL 代码来工作。

标签: sql oracle obiee


【解决方案1】:

理想情况下,更改您的表以将数据存储为 INTERVAL DAY TO SECOND 数据类型,然后您可以只存储 INTERVAL '2:30' HOUR TO MINUTE 并使用日期算术来获得答案。

SELECT ( DATE '1970-01-01' + your_interval_value - DATE '1970-01-01' ) * 24
FROM   DUAL;

由于您存储的是字符串而不是间隔,因此您可以使用NUMTODSINTERVAL 和字符串函数将小时和分钟转换为间隔,然后使用相同的日期算术:

db小提琴here

Oracle 设置

 CREATE TABLE table_name ( value ) AS
 SELECT '2h:30min' FROM DUAL UNION ALL
 SELECT '15min' FROM DUAL UNION ALL
 SELECT '3h' FROM DUAL UNION ALL
 SELECT '26 h : 20 min' FROM DUAL UNION ALL
 SELECT '-2h:30min' FROM DUAL UNION ALL
 SELECT '-4h' FROM DUAL UNION ALL
 SELECT '-45min' FROM DUAL UNION ALL
 SELECT '0h:0min' FROM DUAL UNION ALL
 SELECT '0h' FROM DUAL UNION ALL
 SELECT '-0min' FROM DUAL;

查询

 SELECT value,
        ( DATE '1970-01-01'
        + NUMTODSINTERVAL(
            CASE WHEN INSTR( value, '-' ) > 0 THEN -1 ELSE 1 END
            *
            TO_NUMBER( COALESCE( REGEXP_SUBSTR( value, '(\d*)\s*h', 1, 1, 'i', 1 , '0' ) ),
            'HOUR'
          )
        + NUMTODSINTERVAL(
            CASE WHEN INSTR( value, '-' ) > 0 THEN -1 ELSE 1 END
            *
            TO_NUMBER( COALESCE( REGEXP_SUBSTR( value, '(\d*)\s*min', 1, 1, 'i', 1 ), '0' ) ),
            'MINUTE'
          )
        - DATE '1970-01-01'
        ) * 24 AS hours_difference
 FROM   table_name;

输出

价值 | HOURS_DIFFERENCE :------------ | ----------------------------------------------------: 2 小时:30 分钟 | 2.5 15分钟 | .250000000000000000000000000000000000000008 3 小时 | 3 26 小时:20 分钟 | 26.33333333333333333333333333333333333328 -2 小时:30 分钟 | -2.5 -4 小时 | -4 -45 分钟 | -.75 0h:0min | 0 0h | 0 -0 分钟 | 0

【讨论】:

  • 很遗憾,使用间隔是如此冗长和笨拙
  • @CaiusJard 理想情况下,OP 应该将数据存储为 INTERVAL '2:30' HOUR TO MINUTE 而不是像 2h:30min 这样的字符串,然后您可以跳过字符串转换而只使用日期算术。不幸的是,他们没有为工作使用正确的数据类型,因此解析字符串是必要的。如果 OP 永远不会有负日期,那么他们可以去掉那部分;同样,如果总是有一个小时和一分钟的组成部分,那么可以删除 COALESCE 函数......我的回答中有很多冗余,以应对问题中缺乏规范。
【解决方案2】:

神谕方式:

SELECT (TO_DATE('2h:30min', 'HH24"h":MI"min"') - TO_DATE('0:00', 'HH24:MI')) * 24.0 from dual

它是如何工作的:

  • 2h:30min解析为日期,生成01-JAN-19的日期(所有不带日、月、年的日期解析为当前月/年的第一个)
  • 0:00 解析为日期 -> 同日、同月、同年,但时间为午夜
  • 减去它们,得到一个浮点数,表示两个日期时间之间一天的分数(一天是 1.0,12 小时是 0.5 等)。在这种情况下,这大约为 0.1041667
  • 我们乘以 24 将 0.1041667 天变成小时 -> 2.5

【讨论】:

  • 如果持续时间 > 24 小时怎么办? ;)
  • 使用 Gordon 的解决方案。或者首先正确存储数据! :)
【解决方案3】:

如果将值存储为字符串,则可以提取组件并使用算术。

提取组件的一种方法是获取前两个字符,然后是第 4 和第 5 个字符。 regexp_substr() 提供了更多的灵活性:

select cast(regexp_substr(yyyymm, '[^:]+', 1, 1) as number) + cast(regexp_substr(yyyymm, '[^:]+', 1, 2) as number) / 60
from (select '24:30' as yyyymm from dual) x

【讨论】:

    猜你喜欢
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 2021-08-20
    • 1970-01-01
    • 2020-09-24
    相关资源
    最近更新 更多