将每个日期范围转换为Oracle的每一天

时间:2019-02-27 11:45:35

标签: oracle

我有一张看起来像这样的桌子

 From_date      To_date        EMP_Cod
 2013-01-01     2013-01-04      5150
 2013-01-05     2013-01-06      5151

我该如何将其退回……

      Date         EMP_Cod 
    2013-01-01      5150 
    2013-01-02      5150 
    2013-01-03      5150
    2013-01-04      5150
    2013-01-05      5151
    2013-01-06      5151

我采用了这种方法,但没有成功

    select * FROM emp_vac;
with nums as (
SELECT level-1 daystoadd
form dual 
connect by level <= 60
)
select from_date + daystoadd thedate
from emp_vac
cross join nums
where emp_vac.to_date - emp_vac.from_date + 1 > daystoadd and (emp_ser='5150')
;

在命令行:3列:25上给我错误

请帮助我是新手

3 个答案:

答案 0 :(得分:1)

您发布的代码中唯一明显的错误是您拥有form dual而不是from dual。但是,使用该固定方法后,它并不能提供您想要的输出,因为您只获得日期并且仅针对一名员工:

THEDATE   
----------
2013-01-01
2013-01-02
2013-01-03
2013-01-04

您可以删除过滤器并添加emp_ser值:

with nums as (
SELECT level-1 daystoadd
from dual 
connect by level <= 60
)
select from_date + daystoadd thedate, emp_ser
from emp_vac
cross join nums
where emp_vac.to_date - emp_vac.from_date + 1 > daystoadd -- and (emp_ser='5150')
order by emp_ser, thedate;

THEDATE       EMP_SER
---------- ----------
2013-01-01       5150
2013-01-02       5150
2013-01-03       5150
2013-01-04       5150
2013-01-05       5151
2013-01-06       5151

60天的硬限制有点尴尬。您可以通过单个层次查询获得相同的结果:

select from_date + level - 1 as vac_date, emp_ser
from emp_vac
connect by emp_ser = prior emp_ser
and level <= to_date - from_date + 1
and prior dbms_random.value is not null;

VAC_DATE      EMP_SER
---------- ----------
2013-01-01       5150
2013-01-02       5150
2013-01-03       5150
2013-01-04       5150
2013-01-05       5151
2013-01-06       5151

需要笨拙地调用非确定性函数(在这种情况下为dbms_random.value,但您可以使用其他函数)来正确处理多个源行;或使用recursive subquery factoring

with rcte (vac_date, to_date, emp_ser) as (
  select from_date, to_date, emp_ser
  from emp_vac
  union all
  select vac_date + 1, to_date, emp_ser
  from rcte
  where vac_date < to_date
)
select vac_date, emp_ser
from rcte
order by emp_ser, vac_date;

VAC_DATE      EMP_SER
---------- ----------
2013-01-01       5150
2013-01-02       5150
2013-01-03       5150
2013-01-04       5150
2013-01-05       5151
2013-01-06       5151

此处,锚点成员获取每个记录的开始日期,而递归成员一次添加一天,直到到达结束日期。 (顺便说一句,我建议不要使用to_date之类的函数名作为列名-这是合法的,但令人困惑。)

当然,如果休假时间跨度是周末或其他假期,那么所有这些方法都将包括那些非工作日,这可能并不是您真正想要的。排除周末会相对简单,但是要排除其他假期,您需要一个查找表来标识这些日期。


正如@PonderStibbons在评论中指出的,在某些版本中存在一个带有日期和递归CTE的错误(可能只有11.2.0.1和11.2.0.2-似乎是错误11840579,已在MoS中的11.2.0.3中得到了修复。 );这是Ponder的变通办法,使用数字代替日期作为递归成员限制:

with rcte (rn, diff, from_date, emp_ser) as (
  select 1, trunc(to_date - from_date), from_date, emp_ser from emp_vac
  union all
  select rn + 1, diff, from_date, emp_ser from rcte where rn <= diff )
select from_date + rn - 1 vac_date, emp_ser
from rcte
order by emp_ser, vac_date;

...和db<>fiddle(11.2.0.2)。

答案 1 :(得分:0)

尝试

select (from_Date+r-1), emp_code1 from (
select distinct a.from_Date,a.emp_code as emp_code1 , b.emp_code as emp_code2 , b.r from  emp_vac a,  (Select emp_code, level r
From emp_vac b  
Connect By level <= (to_Date-from_Date)+1  )  b where a.emp_code=b.emp_code
) where emp_code1=emp_code2

答案 2 :(得分:0)

SELECT DISTINCT
 em_code, (to_date(end_date,'DD-MM-YYYY') - level + 1) AS days
FROM
   islaam_vca where em_code = '2222'

CONNECT BY level <= (to_date(end_date,'DD-MM-YYYY') - to_date(start_date,'DD-MM-YYYY') + 1)
order by days ASC
;

我正在测试此代码并与我一起工作