Sql 用于将流程与任务数据隔离的查询

Sql 用于将流程与任务数据隔离的查询,sql,oracle,Sql,Oracle,我在某些流程中有以下任务表: 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 | |

我在某些流程中有以下任务表:

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 |任务|持续时间
----+--------+---------

100 | 3 | 5您可以使用分层查询查找每个链的根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\u BY\u ROOT
是一个一元运算符,仅在分层查询中有效。使用此运算符限定列时,Oracle将使用根行中的数据返回列值。此运算符扩展了分层查询的[Previor]
条件下的
连接功能

因此,不管一行在层次结构中有多少层,您仍然可以看到它与哪个根相关。例如,在这种情况下,前三行都与根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\u ts
列设置为时间戳。如果你的是一个约会,那么你会看到一天的一小部分。无论哪种方式,您都可以将其转换为所需的格式


或者。

干得好!您是在我键入相同答案时这样做的:-)我不需要分层查询来查找根,每一个具有PREV\u ID为NULL的行都是根。@sbrbot-您需要分层查询来通过
connect\u by\u root
操作符来查找ID 102的根是100。否则你怎么把102和100联系起来?
start with prev\u id为null
用于标识根id,是的,但是您需要知道哪些id适用于每个非根行,这样您就可以进行分组和聚合。@AlexPoole感谢您的回答和解释解决方案的专业知识,“connect\u by\u root”操作符对我来说是新事物。
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