Усечение нескольких периодов дат - PullRequest
0 голосов
/ 22 мая 2018

Вот изображение, описывающее таблицу, с которой я работаю (TBL_CHILDREN), а также желаемый результат, который я пытаюсь достичь.

enter image description here

В нужной таблице требуется отдельная строка для каждой новой комбинации активных CHILD_ID под тем же PARENT_ID.Так, например, с 2017-01-01 по 2017-02-28 был активен только CHILD_ID 1, поэтому желаемая таблица имеет строку, охватывающую 2017-01-01 - 2017-02-28.Но затем 2017-03-01 CHILD_ID 2 также вступил в силу, поэтому мне нужна новая строка, чтобы отразить период, когда CHILD_ID 1 и 2 были активны одновременно.И так далее, и так далее, пока у меня не будет строки, описывающей каждый период комбинаций CHILD_ID.

Вот код для TBL_CHILDREN:

WITH TBL_CHILDREN AS (SELECT 57 PARENT_ID, 1 CHILD_ID, TO_DATE('2017-01-01','YYYY-MM-DD') START_DATE, TO_DATE('9999-12-31','YYYY-MM-DD') END_DATE FROM dual UNION ALL
                      SELECT 57 PARENT_ID, 2 CHILD_ID, TO_DATE('2017-03-01','YYYY-MM-DD') START_DATE, TO_DATE('2017-05-31','YYYY-MM-DD') END_DATE FROM dual UNION ALL
                      SELECT 57 PARENT_ID, 3 CHILD_ID, TO_DATE('2017-04-01','YYYY-MM-DD') START_DATE, TO_DATE('2017-10-31','YYYY-MM-DD') END_DATE FROM dual)
SELECT *
FROM TBL_CHILDREN

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Использование UNPIVOT с аналитической функцией LAG или LEAD сделает это при сканировании одной таблицы:

SQL Fiddle

Oracle11g Настройка схемы R2 :

create table TBL_CHILDREN ( parent_id, child_id, start_date, end_date )AS
SELECT 57, 1, DATE '2017-01-01', DATE '9999-12-31' FROM dual UNION ALL
SELECT 57, 2, DATE '2017-03-01', DATE '2017-05-31' FROM dual UNION ALL
SELECT 57, 3, DATE '2017-04-01', DATE '2017-10-31' FROM dual;

Запрос 1 :

SELECT *
FROM   (
  SELECT PARENT_ID,
         DT AS start_date,
         LEAD( DT ) OVER ( PARTITION BY parent_id ORDER BY DT ) AS end_date
  FROM   TBL_CHILDREN
  UNPIVOT( dt FOR start_end IN ( start_date, end_date ) )
)
WHERE  end_date IS NOT NULL

Результаты :

| PARENT_ID |           START_DATE |             END_DATE |
|-----------|----------------------|----------------------|
|        57 | 2017-01-01T00:00:00Z | 2017-03-01T00:00:00Z |
|        57 | 2017-03-01T00:00:00Z | 2017-04-01T00:00:00Z |
|        57 | 2017-04-01T00:00:00Z | 2017-05-31T00:00:00Z |
|        57 | 2017-05-31T00:00:00Z | 2017-10-31T00:00:00Z |
|        57 | 2017-10-31T00:00:00Z | 9999-12-31T00:00:00Z |

Запрос 2 , и он будет получать идентификаторы родителя и ребенка для каждого периода времени:

SELECT *
FROM   (
  SELECT parent_id,
         ( SELECT LISTAGG( child_id, ',' ) WITHIN GROUP ( ORDER BY child_id )
           FROM   TBL_CHILDREN c
           WHERE  u.dt >= c.START_DATE
           AND    u.dt <  c.END_DATE ) AS child_ids,
         DT AS start_date,
         LEAD( DT ) OVER ( PARTITION BY parent_id ORDER BY DT ) AS end_date
  FROM   TBL_CHILDREN
  UNPIVOT( dt FOR start_end IN ( start_date, end_date ) ) u
)
WHERE  end_date IS NOT NULL

Результаты :

| PARENT_ID | CHILD_IDS |           START_DATE |             END_DATE |
|-----------|-----------|----------------------|----------------------|
|        57 |         1 | 2017-01-01T00:00:00Z | 2017-03-01T00:00:00Z |
|        57 |       1,2 | 2017-03-01T00:00:00Z | 2017-04-01T00:00:00Z |
|        57 |     1,2,3 | 2017-04-01T00:00:00Z | 2017-05-31T00:00:00Z |
|        57 |       1,3 | 2017-05-31T00:00:00Z | 2017-10-31T00:00:00Z |
|        57 |         1 | 2017-10-31T00:00:00Z | 9999-12-31T00:00:00Z |
0 голосов
/ 22 мая 2018

Пожалуйста, посмотрите на это демо

WITH qqq AS (
  SELECT * FROM TBL_CHILDREN
  START WITH child_id = 1
  CONNECT BY PRIOR parent_id = parent_id AND PRIOR child_id + 1 = child_id
)
SELECT * FROM (
  SELECT PARENT_ID, 
         d as start_date,
         lead(d) over (partition by PARENT_ID order by d ) - 1 as end_date
  FROM (
    SELECT PARENT_ID, start_date as d FROM qqq
    UNION
    SELECT PARENT_ID, end_date FROM qqq
  )
)
WHERE end_date is not null
ORDER by PARENT_ID, start_date
;

| PARENT_ID |           START_DATE |             END_DATE |
|-----------|----------------------|----------------------|
|        57 | 2017-01-01T00:00:00Z | 2017-02-28T00:00:00Z |
|        57 | 2017-03-01T00:00:00Z | 2017-03-31T00:00:00Z |
|        57 | 2017-04-01T00:00:00Z | 2017-05-30T00:00:00Z |
|        57 | 2017-05-31T00:00:00Z | 2017-10-30T00:00:00Z |
|        57 | 2017-10-31T00:00:00Z | 9999-12-30T00:00:00Z |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...