Конвертировать каждый диапазон дат в каждую строку дня Oracle - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть таблица, которая выглядит следующим образом

 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 голосов
/ 27 февраля 2019

попробуйте

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
0 голосов
/ 07 марта 2019
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
;

это работа, я тестирую этот код и работаю со мной

0 голосов
/ 27 февраля 2019

Единственная очевидная ошибка в размещенном вами коде - это то, что у вас есть 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, но вы можете использовать другие) для правильной работынесколько исходных строк;или с рекурсивным факторингом подзапроса :

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, которая показана как исправленная в 11.2.0.3 в MoS);Это обходной путь для 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).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...