Sql 按时间间隔划分一段时间

Sql 按时间间隔划分一段时间,sql,oracle,gaps-and-islands,Sql,Oracle,Gaps And Islands,我有一个表,其中包含代表“个人职业”的多个时间段,在同一个表中,我有与同一个人有关的所有中断,即假期、疾病 表中使用的订单是按代码任务排序的,然后是年份,然后是工作类型,然后是假期,第二个是周期 Date begin Date end Type codeMission year name ---------- -------------------------------------------- 2001-01-01 2001-12-31 Working Tx100

我有一个表,其中包含代表“个人职业”的多个时间段,在同一个表中,我有与同一个人有关的所有中断,即假期、疾病

表中使用的订单是按代码任务排序的,然后是年份,然后是工作类型,然后是假期,第二个是周期

 Date begin Date end   Type    codeMission  year  name
 ---------- --------------------------------------------
 2001-01-01 2001-12-31 Working     Tx100     2001  James
 2001-05-01 2001-05-12 holidays    Tx100     2001  James
我想把工作时间按假期时间分开

 Date begin Date end   Type    codeMission  year  name
 ---------- -----------------------------------------
 2001-01-01 2001-04-30 Working    Tx100     2001  James
 2001-05-01 2001-05-12 holiday    Tx100     2001  James
 2001-05-13 2001-12-31 Working    Tx100     2001  James
有没有一个通用的方法可以做到这一点?如你所知,假期/疾病时间有时可以是在某个时间之前或之后

问题1:如何获得包含所有列的格式?我想在这里提到一个具体问题, 问题2:当假日期限确定为两年时。例如:

Date begin Date end   Type    codeMission  year  name
 ---------- --------------------------------------------
 2001-01-01 2001-12-31 Working     Tx100     2001  James
 2001-10-11 2002-04-30 holidays    Tx100     2001  James
 2002-01-01 2001-12-31 Working     Tx100     2002  James
在这里我们将得到多个问题!!!划分的周期不正确!!
你觉得怎么样?

这相当复杂。这样做的目的是取消日期标记,并跟踪每天输入或输出的类型。然后,您可以使用累计和来跟踪实际类型

因此:

他是一把小提琴

编辑:

是一个改进的版本:

with t as (
      select date '2001-01-01' as sdate, date '2001-12-31' as edate, 'Working' as type from dual union all
      select date '2001-05-01' as sdate, date '2001-05-12' as edate, 'holidays' from dual union all
      select date '2001-07-01' as sdate, date '2001-08-12' as edate, 'holidays' from dual
     ),
     d as (
      select sdate as dte from t union all
      select edate + 1 from t
     )
select d.dte, d.enddte,
       (select max(t2.type) keep (dense_rank first order by t2.sdate desc)
        from t t2
        where t2.sdate <= d.dte and t2.edate >= d.enddte
       ) as type 
from (select d.*, lead(dte) over (order by dte) - 1 as enddte
      from d
     ) d
where dte <= enddte
order by d.dte
这种方法只是通过分解原始周期来获得各个周期。然后,对于每个期间,它会找到在该期间有效的类型。这是涵盖整个时期的最新记录


请注意,由于日期是相邻的,因此没有对时段的部分覆盖。

这相当复杂。这样做的目的是取消日期标记,并跟踪每天输入或输出的类型。然后,您可以使用累计和来跟踪实际类型

因此:

他是一把小提琴

编辑:

是一个改进的版本:

with t as (
      select date '2001-01-01' as sdate, date '2001-12-31' as edate, 'Working' as type from dual union all
      select date '2001-05-01' as sdate, date '2001-05-12' as edate, 'holidays' from dual union all
      select date '2001-07-01' as sdate, date '2001-08-12' as edate, 'holidays' from dual
     ),
     d as (
      select sdate as dte from t union all
      select edate + 1 from t
     )
select d.dte, d.enddte,
       (select max(t2.type) keep (dense_rank first order by t2.sdate desc)
        from t t2
        where t2.sdate <= d.dte and t2.edate >= d.enddte
       ) as type 
from (select d.*, lead(dte) over (order by dte) - 1 as enddte
      from d
     ) d
where dte <= enddte
order by d.dte
这种方法只是通过分解原始周期来获得各个周期。然后,对于每个期间,它会找到在该期间有效的类型。这是涵盖整个时期的最新记录


请注意,由于日期相邻,因此不会对时段进行部分覆盖。

提示:间隙和岛屿提示:间隙和岛屿幸运的是,如果在一个工作时段内有多个非工作时段,则这不起作用;事情出了差错@博内斯特。这真是个好机会。这不是解决第一个问题,而是采用不同的方法。@Boneist。我看到了第一个查询的问题。我再次修改了答案。这样更好,但对于连续缺勤似乎不起作用,例如@Boneist。如果您需要QA职位的推荐;不幸的是,如果你在一个工作期间内有多个非工作期间,那么这就不起作用了;事情出了差错@博内斯特。这真是个好机会。这不是解决第一个问题,而是采用不同的方法。@Boneist。我看到了第一个查询的问题。我再次修改了答案。这样更好,但对于连续缺勤似乎不起作用,例如@Boneist。如果您需要QA职位的推荐;