Это один из подходов, который вы можете использовать.Создайте список возможных времен (в вашем случае, вплоть до секунд) и используйте «существует» или присоедините его к таблице, чтобы получить секунды для каждого идентификатора.
*Изменить: Новый пример с использованием существует вместо Join .. больше в соответствии с вопросом, что запрос пытается ответить .. (На сколько секунд работал хотя бы один активный процесс ..?).Установите данные под запросом ... * '
select count(time1) from
(
/* All possible seconds in the time frame you want to track */
select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
) all_times
where exists (
/* Atleast one process is running at that second...*/
select 1
from t1
where t1.start_time < all_times.time1
and t1.end_time >= all_times.time1
)
Count(time1)
11
Для простоты понимания я взял только 4 случая / записи.Первые три записи пересекаются, а последняя представляет собой полную непересекающуюся запись.
create table t1(
id number,
start_time date,
end_time date
);
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:00','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:05','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:02','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:04','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:03','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:06','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:15','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:20','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> commit;
alter session set NLS_DATE_FORMAT = "MM/DD/YYYY HH24:MI:SS";
SQL> select * from t1;
ID START_TIME END_TIME
---------- ------------------- -------------------
1 07/15/2011 12:00:00 07/15/2011 12:00:05
1 07/15/2011 12:00:02 07/15/2011 12:00:04
1 07/15/2011 12:00:03 07/15/2011 12:00:06
1 07/15/2011 12:00:15 07/15/2011 12:00:20
Эта часть возвращает вам список всех времен (до секунд) 15 июля ...
select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
Присоедините это к основному столу, и вы получите это ... (каждую минуту, в которую запущен процесс ...)
SQL > break on id on start_time on end_time
select t1.id,
t1.start_time,
t1.end_time,
all_seconds.time1
from t1,
(select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
) all_seconds
where all_seconds.time1 > t1.start_time
and all_seconds.time1 <= t1.end_time
ID START_TIME END_TIME TIME1
---------- ------------------- ------------------- -------------------
1 07/15/2011 12:00:00 07/15/2011 12:00:05 07/15/2011 12:00:01
07/15/2011 12:00:02
07/15/2011 12:00:03
07/15/2011 12:00:04
07/15/2011 12:00:05
2 07/15/2011 12:00:02 07/15/2011 12:00:04 07/15/2011 12:00:03
07/15/2011 12:00:04
3 07/15/2011 12:00:03 07/15/2011 12:00:06 07/15/2011 12:00:04
07/15/2011 12:00:05
07/15/2011 12:00:06
4 07/15/2011 12:00:15 07/15/2011 12:00:20 07/15/2011 12:00:16
07/15/2011 12:00:17
07/15/2011 12:00:18
07/15/2011 12:00:19
07/15/2011 12:00:20
Отсюда ... Все, что вам нужно, это отличноеотсчет минут.Если у вас есть другой столбец для группировки, вам нужно будет изменить этот запрос в конце.(пример ... Проекты, даты начала и даты окончания ... для которых вы хотите общее количество рабочих дней .., вам нужно сгруппировать по project_id (??))
select count(distinct(time1)) total_minutes
from (
select t1.id,
t1.start_time,
t1.end_time,
all_seconds.time1
from t1,
(select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
) all_seconds
where all_seconds.time1 > t1.start_time
and all_seconds.time1 <= t1.end_time
)
/
TOTAL_MINUTES
-------------
11
Проблема сэто решение состоит в том, что это (более или менее) грубая сила.Вы должны создать список всех возможных времен (если у вас есть данные, охватывающие несколько дат, и вам нужно время обработки с точностью до секунд, сгенерированные данные будут огромными).В зависимости от того, насколько велика ваша фактическая таблица, соединение может быть неэффективным.
Я все еще пытаюсь выяснить, можно ли это изящно решить с помощью аналитики.Выложу здесь, если я найду лучшее решение.