Разверните диапазон дат, чтобы получить все даты между сериями диапазонов дат из таблицы с исключенными датами - PullRequest
0 голосов
/ 15 октября 2018

Мне нужно получить все даты от DATE_FROM до DATE_TO каждого ID таблицы LEAVE, исключая выходные, рабочие отстранения и праздничные дни.Учитывая эту запись (ID, DATE_FROM, DATE_TO):

001   04-OCT-2018   09-OCT-2018
002   05-OCT-2018   05-OCT-2018
...
n     01-OCT-2018   05-OCT-2018

Мне нужно получить все даты между этими диапазонами в этом формате (ID, DAY_TOKEN):

001  04-OCT-2018
001  05-OCT-2018
001  08-OCT-2018
001  09-OCT-2018
002  05-OCT-2018
...
n    01-OCT-2018
n    02-OCT-2018
n    03-OCT-2018
n    04-OCT-2018
n    05-OCT-2018

Я использую этот запрос, модифицированный из найденных мной запросов:

SELECT ID, a.date_from + rnum - 1 AS day_token
  FROM (SELECT a.ID, a.date_from, a.date_to, ROWNUM AS rnum
          FROM all_objects, leave a
          -- Aside from ALL_OBJECT, I cross join it with my LEAVE table
         WHERE ROWNUM <= a.date_to - a.date_from + 1) a
 WHERE TO_CHAR (a.date_from + rnum - 1, 'DY') NOT IN ('SAT', 'SUN');
   AND NOT EXISTS (SELECT 1
                     FROM holiday b
                    WHERE b.schedule = d.date_from + rnum - 1)
   AND NOT EXISTS (SELECT 1
                     FROM suspension c
                    WHERE c.schedule = d.date_from + rnum - 1)

Проблема заключается в том, что только первая запись будет расширена должным образом, а другие записи не будут включены внабор записей, если только DATE_FROM и DATE_TO не имеют одинаковую дату.

Я хочу избегать максимально возможного использования функции PL-SQL, но если невозможно добиться нужного мне набора результатов без использованияфункция, пожалуйста, сообщите мне хотя бы причину.

1 Ответ

0 голосов
/ 15 октября 2018

Вот как можно создать столько строк для каждого идентификатора, сколько есть дней между датами ОТ и ДО, без выходных (суббота и воскресенье):

SQL> with leave (id, date_from, date_to) as
  2  (select '001', date '2018-10-04', date '2018-10-09' from dual union all
  3   select '002', date '2018-10-05', date '2018-10-05' from dual union all
  4   select '003', date '2018-10-02', date '2018-10-08' from dual
  5  ),
  6  inter as
  7    (select l.id,
  8       l.date_from + column_value datum,
  9       to_char(l.date_from + column_value, 'day') day
 10     from leave l,
 11          table(cast(multiset(select level from dual
 12                              connect by level <= l.date_to - l.date_from + 1
 13                             ) as sys.odcinumberlist))
 14    )
 15  select id, datum
 16  from inter
 17  where to_char(datum, 'dy') not in ('sat', 'sun');

ID  DATUM
--- -----------
001 05-oct-2018
001 08-oct-2018
001 09-oct-2018
001 10-oct-2018
003 03-oct-2018
003 04-oct-2018
003 05-oct-2018
003 08-oct-2018
003 09-oct-2018

9 rows selected.

SQL>

В строке 18 (и т. Д.) Добавитьдополнительные условия (убрать праздники, отстранение от работы и т. д.).

(Кстати, мне интересно, кто и почему отклонил ваш вопрос; он правильно сформулирован, показывает, что у вас есть, ваша попытка его решить ... действительнодля меня загадка).

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