【问题标题】:How to take Average of Duration in Hour & Minute in SQL?如何在 SQL 中以小时和分钟为单位取平均持续时间?
【发布时间】:2013-10-11 16:06:11
【问题描述】:

我需要对表中的一列取平均值。它有小时和分钟格式的持续时间。

查询

select DURATIONHM from TableT where nownum < 9.

输出

DURATIONHM
--------------------------------
5 hrs 5 min
2 hrs 20 min
1 hrs 29 min
1 hrs 45 min
4 hrs 10 min
3 hrs 35 min
1 min
32 min
1 hrs 16 min

9 rows selected.

必需的输出。

我需要取平均值DURATIONHM

select avg(DURATIONHM) as DurationTime from TableT

错误

ERROR at line 1:
ORA-01722: invalid number

我还需要Hour &amp; Minute.的输出

【问题讨论】:

  • 嗯...您必须解析输入数据,然后将其全部转换为分钟,然后取平均值,最后将数字重新格式化为原始格式。糟糕的工作和查询。下次你应该考虑正确保存数据:)

标签: sql oracle datetime oracle11g sqlplus


【解决方案1】:

如果你使用 regexp_substr,那还不错:

CREATE TABLE tablet (durationhm VARCHAR2(20));

INSERT INTO tablet VALUES ('5 hrs 5 min');
INSERT INTO tablet VALUES ('2 hrs 20 min');
INSERT INTO tablet VALUES ('1 hrs 29 min');
INSERT INTO tablet VALUES ('1 hrs 45 min');
INSERT INTO tablet VALUES ('4 hrs 10 min');
INSERT INTO tablet VALUES ('3 hrs 35 min');
INSERT INTO tablet VALUES ('1 min');
INSERT INTO tablet VALUES ('32 min');
INSERT INTO tablet VALUES ('1 hrs 16 min');

COMMIT;

SELECT (NVL(regexp_substr(durationhm, '([0-9]+) hrs', 1, 1, NULL, 1), 0) * 60
        + NVL(regexp_substr(durationhm, '([0-9]+) min', 1, 1, NULL, 1), 0)) AS number_of_minutes
  FROM tablet;

NUMBER_OF_MINUTES      
---------------------- 
305                    
140                    
89                     
105                    
250                    
215                    
1                      
32                     
76                

SELECT AVG(NVL(regexp_substr(durationhm, '([0-9]+) hrs', 1, 1, NULL, 1), 0) * 60
        + NVL(regexp_substr(durationhm, '([0-9]+) min', 1, 1, NULL, 1), 0)) AS average_time
  FROM tablet;

AVERAGE_TIME           
---------------------- 
134,777777777777777777777777777777777778

在 SQLFiddle 检查:http://sqlfiddle.com/#!4/ad58c/1

编辑:抱歉,没看到您也想以#of_hours hrs #of_minutes min 格式获得答案。它变得丑陋,但有效(目前不确定如何编写看起来更好的查询):

SELECT 
    CASE
      WHEN average_time >= 60 THEN trunc(average_time / 60) || ' hrs'
                                    || 
                                      CASE
                                        WHEN MOD(average_time, 60) = 0 THEN NULL
                                        ELSE ' ' || MOD(average_time, 60) || ' min'
                                      END
      ELSE MOD(average_time, 60) || ' min'
    END AS average_formatted
  FROM (
    SELECT TRUNC(AVG(NVL(regexp_substr(durationhm, '([0-9]+) hrs', 1, 1, NULL, 1), 0) * 60
          + NVL(regexp_substr(durationhm, '([0-9]+) min', 1, 1, NULL, 1), 0))) AS average_time
      FROM tablet
);

好吧,想出了另一种可能性(虽然很丑):

SELECT
 RTRIM(DECODE(TRUNC(average_time / 60), 0, NULL, trunc(average_time / 60) || ' hrs ') ||
    DECODE(MOD(average_time, 60), 0, NULL, MOD(average_time, 60) || ' min'))
      AS average_formatted
  FROM (
    SELECT TRUNC(AVG(NVL(regexp_substr(durationhm, '([0-9]+) hrs', 1, 1, NULL, 1), 0) * 60
          + NVL(regexp_substr(durationhm, '([0-9]+) min', 1, 1, NULL, 1), 0))) AS average_time
      FROM tablet
);

【讨论】:

  • 首先感谢您的帮助,其次我需要Hours &amp; Minutes 中的最后一个average_time,我该如何获得?
  • 我又添加了一个查询,它很丑,但如果你愿意,你可以改进它。目前没有其他想法如何让它看起来更好。
  • 非常感谢,我知道这很复杂,我终于放弃了,把问题贴在这里。再次感谢您的帮助:)
  • Two more ways to get the time 如果您正在收集它们;虽然第一个需要进一步操作......
猜你喜欢
  • 1970-01-01
  • 2017-03-25
  • 2017-05-16
  • 1970-01-01
  • 1970-01-01
  • 2014-02-27
  • 2019-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多