我在某些流程中有以下任务表:
ID | PREV_ID | NEXT_ID | TASK_TS
----+---------+---------+--------------------
100 | | 101 | 2013-01-10 10:22:00
101 | 100 | 102 | 2013-01-10 10:25:12
102 | 101 | | 2013-01-10 10:27:00
103 | | 104 | 2013-01-10 10:31:00
104 | 103 | | 2013-01-10 10:35:00
105 | | | 2013-01-10 10:38:22
ID是任务ID,PREV_ID是进程链中先前任务的ID,NEXT_ID是进程链中下一个任务的ID,TASK_TS是任务(事件)发生时的时间戳。
我需要查询来隔离此表中用启动任务ID表示的进程,计算进程中的任务数和进程持续时间(进程任务链中最后一个和第一个任务之间的差异),以分钟/小时/天为单位(并不重要。
ID | TASKS | DURATION
----+--------+---------
100 | 3 | 5 <-- this process has 3 tasks and lasted 5 mins
103 | 2 | 4 <-- this process has 2 tasks and lasted 4 mins
105 | 1 | 0 <-- this process has only 1 task and lasted 0 mins
答案 0 :(得分:1)
您可以使用分层查询来查找每个链的根ID(即第一个任务):
select t.*, connect_by_root id as root_id
from t42 t
connect by id = prior next_id
start with prev_id is null;
ID PREV_ID NEXT_ID TASK_TS ROOT_ID
---------- ---------- ---------- ---------------------------- ----------
100 101 10-JAN-13 10.22.00.000000000 100
101 100 102 10-JAN-13 10.25.12.000000000 100
102 101 10-JAN-13 10.27.00.000000000 100
103 104 10-JAN-13 10.31.00.000000000 103
104 103 10-JAN-13 10.35.00.000000000 103
105 10-JAN-13 10.38.22.000000000 105
CONNECT_BY_ROOT
是一元运算符,仅在分层查询中有效。使用此运算符限定列时,Oracle将使用根行中的数据返回列值。此运算符扩展了分层查询的CONNECT BY [PRIOR]
条件的功能。
因此,无论层次结构中的层次是多少,您仍然可以看到它与哪个根相关。在这种情况下,前三行都与根ID 100相关,例如;在没有遍历层次结构的情况下,对于ID 102来说并不明显。
然后,您可以将该分层查询用作基于根ID分组的子查询:
select root_id as id, count(*) as tasks,
max(task_ts) - min(task_ts) as duration
from (
select t.*, connect_by_root id as root_id
from t42 t
connect by id = prior next_id
start with prev_id is null
)
group by root_id
order by root_id;
ID TASKS DURATION
---------- ---------- -----------
100 3 0 0:5:0.0
103 2 0 0:4:0.0
105 1 0 0:0:0.0
此处的持续时间是一个时间间隔(一天到一秒),因为我将task_ts
列设为时间戳。如果你的确是一个约会,那么你将会看到一天中的一小部分。无论哪种方式,您都可以将其转换为您想要的格式。