Sql 计算多行之间的时间差并求和

Sql 计算多行之间的时间差并求和,sql,oracle,oracle10g,Sql,Oracle,Oracle10g,我有一个子表,其中包含特定父记录的状态历史记录 该表将是: Parent_id NUMBER(38) Date_Created DATE Status VARCHAR2(15) 样本数据: 1, sysdate-20, REQ 1, sysdate-10, INPRG 1, sysdate-5, WAIT 1, sysdate-2, INPRG 1, sysdate, COMP 对于任何特定的父id,如何计算父id处于特定状态的总时间?假设计算是创建下一个状态的日期减去创建记录的日期。请记

我有一个子表,其中包含特定父记录的状态历史记录

该表将是:

Parent_id NUMBER(38)
Date_Created  DATE
Status VARCHAR2(15)
样本数据:

1, sysdate-20, REQ
1, sysdate-10, INPRG
1, sysdate-5, WAIT
1, sysdate-2, INPRG
1, sysdate, COMP
对于任何特定的父id,如何计算父id处于特定状态的总时间?假设计算是创建下一个状态的日期减去创建记录的日期。请记住,该状态可能会出现多次

对于示例数据,如何计算记录处于“INPRG”状态的总时间

它必须完全在Oracle SQL中完成。没有功能、程序、包等


提前感谢。

您可以使用分析功能
LEAD
LAG
访问结果集中下一行或上一行的数据。这样的东西会给你在每个状态下的总时间

SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2    select 1 parent_id, sysdate-20 date_created, 'REQ' status from dual
  3    union all
  4    select 1, sysdate-10, 'INPRG' from dual
  5    union all
  6    select 1, sysdate-5, 'WAIT' from dual
  7    union all
  8    select 1, sysdate-2, 'INPRG' from dual
  9    union all
 10    select 1, sysdate, 'COMP' from dual
 11  )
 12  select parent_id,
 13         status,
 14         sum(time_in_status)
 15    from (
 16      select parent_id,
 17             date_created,
 18             nvl(lead(date_created) over
 19                          (partition by parent_id
 20                               order by date_created),
 21                 sysdate) next_status_date,
 22             nvl(lead(date_created) over
 23                          (partition by parent_id
 24                               order by date_created),
 25                 sysdate) -
 26               date_created time_in_status,
 27             status
 28        from t)
 29*  group by parent_id, status
SQL> /

 PARENT_ID STATU SUM(TIME_IN_STATUS)
---------- ----- -------------------
         1 REQ                    10
         1 COMP                    0
         1 WAIT                    3
         1 INPRG                   7

您可以使用分析功能
LEAD
LAG
访问结果集中下一行或上一行的数据。这样的东西会给你在每个状态下的总时间

SQL> ed
Wrote file afiedt.buf

  1  with t as (
  2    select 1 parent_id, sysdate-20 date_created, 'REQ' status from dual
  3    union all
  4    select 1, sysdate-10, 'INPRG' from dual
  5    union all
  6    select 1, sysdate-5, 'WAIT' from dual
  7    union all
  8    select 1, sysdate-2, 'INPRG' from dual
  9    union all
 10    select 1, sysdate, 'COMP' from dual
 11  )
 12  select parent_id,
 13         status,
 14         sum(time_in_status)
 15    from (
 16      select parent_id,
 17             date_created,
 18             nvl(lead(date_created) over
 19                          (partition by parent_id
 20                               order by date_created),
 21                 sysdate) next_status_date,
 22             nvl(lead(date_created) over
 23                          (partition by parent_id
 24                               order by date_created),
 25                 sysdate) -
 26               date_created time_in_status,
 27             status
 28        from t)
 29*  group by parent_id, status
SQL> /

 PARENT_ID STATU SUM(TIME_IN_STATUS)
---------- ----- -------------------
         1 REQ                    10
         1 COMP                    0
         1 WAIT                    3
         1 INPRG                   7

我主要使用SQL Server,而不是Oracle,所以请原谅我的语法有点不正确

with base as (
  select Parent_id, Date_Created, Status,
    row_number() over(partition by Parent_id order by Date_Created) as 'row'
  from Table
)
select Parent_id, Status, sum(timeInStatus)
from (
  select this.Parent_id, this.Status,
    next.Date_Created-this.Date_Created as 'timeInStatus'
  from base this
    join base next on this.Parent_id=next.Parent_id
                  and this.row=next.row-1
  ) t
where Status = 'INPRG'
group by Parent_id, Status

基本概念是利用
行数
将每一行自连接到下一行,并计算它们之间的时间。然后,它只是一个简单的数据聚合,以获得您想要的答案。

我主要使用SQL Server,而不是Oracle,请原谅我的语法有点不正确

with base as (
  select Parent_id, Date_Created, Status,
    row_number() over(partition by Parent_id order by Date_Created) as 'row'
  from Table
)
select Parent_id, Status, sum(timeInStatus)
from (
  select this.Parent_id, this.Status,
    next.Date_Created-this.Date_Created as 'timeInStatus'
  from base this
    join base next on this.Parent_id=next.Parent_id
                  and this.row=next.row-1
  ) t
where Status = 'INPRG'
group by Parent_id, Status
基本概念是利用
行数
将每一行自连接到下一行,并计算它们之间的时间。然后,它只是一个简单的数据聚合,以获得您想要的答案