oracle中如何计算char数据类型的求和时间

how to calculate sum time with data type char in oracle

我正在尝试创建一个查询,以对来自 2 table 个不同的 oracle 中数据类型为 char 的记录求和。我有这样的 table :

table 1:

name             time_rent
---------------- -----------
james            07:30

nametime 是 char

table 2:

name             time_expired
---------------- -----------
james            18:30

nametime 是 char

如何使用总和来显示记录以获得总时间(持续时间),是否可能?。我使用 Oracle Database 18c 企业版在 Oracle Live SQL 中编码和测试它。

WITH x AS (
  SELECT t1.time_rent AS t1,
         t2.time_rent AS t2,
         ((SUBSTR(t1.time_rent,1,2) * 3600) + (SUBSTR(t1.time_rent,4,2) * 60)
         + (SUBSTR(t2.time_rent,1,2) * 3600) + (SUBSTR(t2.time_rent,4,2) * 60)) AS t 
   FROM table1 t1 
   INNER JOIN Table2 t2 
   ON t1.name=t2.name
  ),
y AS(
   SELECT t1,
          t2,
          numtodsinterval(t,'second') AS t
          FROM x
)
SELECT T1,
       T2,
       (EXTRACT(day FROM t) * 24 + EXTRACT(hour FROM t) ||':' || 
       EXTRACT(minute FROM t) ||':' || EXTRACT(second FROM t)) AS duration 
       FROM y

输出

T1      T2      DURATION
07:30   18:30   26:0:0

现场演示

http://sqlfiddle.com/#!4/aaa519/12

给您的重要建议:请不要将时间间隔存储为字符串 (CHAR/ VARCHAR2)。这使得在编写查询时更难实现对它们的操作,并且在大型数据集上执行效率低下。

Oracle 为您提供了两种数据类型,正是您希望在数据库中存储的这种区间记录。

INTERVAL

INTERVAL YEAR [(year_precision)] TO MONTH - 以年和月为单位存储一段时间

INTERVAL DAY [(day_precision)] TO SECOND [(fractional_seconds)] - 存储一段时间 日、时、分、秒

第二种类型对您有用,可以将所需的值存储为 INTERVAL .. HOUR to MINUTE

例如:- INTERVAL '07:30' HOUR TO MINUTE

因此,求和运算本来可以很简单,time_rent + time_expired,这可以使运算更容易。现在,由于您已将它们存储为字符,Oracle 确实为您提供了救援功能:

TO_DSINTERVAL - TO_DSINTERVALCHAR, VARCHAR2, NCHAR, or NVARCHAR2 数据类型的字符串转换为 INTERVAL DAY TO SECOND.

因此,将 DAY 分量和秒分量(零)附加到您的时间列将有助于将它们转换为 INTERVAL 类型:TO_DSINTERVAL('000 '|| time_rent|| ':00')

因此,您的最终查询将类似于。

WITH t
     AS (SELECT t1.name,
                  TO_DSINTERVAL('000 '||    time_rent|| ':00')
                + TO_DSINTERVAL('000 '|| time_expired|| ':00') AS intv
         FROM   table1 t1
                join table2 t2
                        ON t1.name = t2.name)
SELECT name,
       EXTRACT(day FROM intv) * 24 + EXTRACT(hour FROM intv) --hours
       || ':'
       || EXTRACT(minute FROM intv) as duration  -- minutes
FROM   t;  

由于加法操作使得总时长超过24小时(26),默认间隔为1 day 2 hoursEXTRACT 函数用于以所需的 HH:MM 格式获取 o/p。您可以使用 EXTRACT 函数从间隔(day.hour、分钟、秒 ..)中检索任何组件并修改查询以以所需格式显示。

Demo