2016-04-11 1 views
0

Моя таблица содержит время хранятся в виде строк:Как рассчитать среднее время, сохраненное в виде строк?

select s.average from Tabela s; 

AVERAGE 
-------- 
1:26:27 
0:10:03 
0:10:04 
0:10:15 
0:09:40 
0:09:32 
0:09:55 

Мне нужно, чтобы получить среднее тех времен. Я пытался использовать:

select avg(to_char(to_timestamp(s.average,'hh24:mi:ss'))) from Tabela s 

Но я не могу использовать avg() подобное; он получает «ORA-01722: недопустимое число».

Как рассчитать среднее значение этих значений времени?

ответ

0

Вы преобразовываете строку в метку времени, затем возвращаетесь к строке, а затем пытаетесь ее усреднить. Однако вы не можете усреднять значение метки времени.

Вы можете преобразовать каждую строку в то время на номинальную дату, и получить смещение от фиксированной даты (например, даты эпохальной для удобства), которая будет несколько дней, включая дробные части:

select average, 
    to_date(average, 'HH24:MI:SS') as dt, 
    to_date(average, 'HH24:MI:SS') - date '1970-01-01' as dt_diff 
from tabela; 

AVERAGE DT      DT_DIFF 
------- ------------------- ------------- 
1:26:27 2016-04-01 01:26:27 16892.06003 
0:10:03 2016-04-01 00:10:03 16892.00698 
0:10:04 2016-04-01 00:10:04 16892.00699 
0:10:15 2016-04-01 00:10:15 16892.00712 
0:09:40 2016-04-01 00:09:40 16892.00671 
0:09:32 2016-04-01 00:09:32 16892.00662 
0:09:55 2016-04-01 00:09:55 16892.00689 

Вы можете затем усреднить эту разницу число-дней, и добавить его в ту же фиксированную дату, и, наконец, извлечь временную часть в виде строки:

select avg(to_date(average, 'HH24:MI:SS') - date '1970-01-01') as avg_dt_diff, 
    to_char(date '1970-01-01' + avg(to_date(average, 'HH24:MI:SS') - date '1970-01-01'), 
    'HH24:MI:SS') as result 
from tabela; 

    AVG_DT_DIFF RESULT 
------------- -------- 
    16892.01448 00:20:51 

Это будет работать только, если строка все они представляют менее 24 часов; to_date() не удастся, если вы превысите это.


Вы также можете сделать это с интервалами, но они немного больше боли работать:

select average, to_dsinterval('0 ' || average) as avg_int 
from tabela; 

AVERAGE AVG_INT 
------- ----------- 
1:26:27 0 1:26:27.0 
0:10:03 0 0:10:3.0 
0:10:04 0 0:10:4.0 
0:10:15 0 0:10:15.0 
0:09:40 0 0:9:40.0 
0:09:32 0 0:9:32.0 
0:09:55 0 0:9:55.0 

А затем извлечь количество секунд и конвертировать в другой интервал:

select numtodsinterval(avg((extract(hour from avg_int) * 60 * 60) 
    + (extract(minute from avg_int) * 60) 
    + extract(second from avg_int)), 'SECOND') as result 
from (
    select to_dsinterval('0 ' || average) as avg_int 
    from tabela 
); 

RESULT  
------------------- 
0 0:20:50.857142857 

Это более точно, но вам нужно будет извлечь элементы еще раз, чтобы получить строку.