Даты перекрытия Oracle - PullRequest
       138

Даты перекрытия Oracle

1 голос
/ 06 августа 2020

У меня есть набор диапазона дат, где он может иметь значения конфигурации как 'S' или 'D', но нижний диапазон дат может иметь перекрывающиеся даты, и я пытаюсь получить значения конфигурации для соответствующей даты.

Примечание: если значение конфигурации равно 'D', диапазон дат будет в пределах диапазона данных другой строки, содержащей значение конфигурации 'S', если оно существует.

Данные:

Start_DATE       End_Date    Config
01-Jan-2020      31-Jan-2020    S
15-Jan-2020      20-Jan-2020    D
15-Feb-2020      20-Feb-2020    D
01-Mar-2020      20-Mar-2020    S

Я хотел получить результат вроде

Start_DATE       End_Date    Config
01-Jan-2020      14-Jan-2020    S
15-Jan-2020      20-Jan-2020    D
16-Jan-2020      31-Jan-2020    S
15-Feb-2020      20-Feb-2020    D
01-Mar-2020      20-Mar-2020    S

Пробовал несколько вещей, но ничего не понял для меня ..

Logi c:

  1. Значение конфигурации «S» или «D» может перекрываться в заданном диапазоне дат.
  2. Запрос должен извлечь, где для диапазона дат указано «S» или «D»

1 Ответ

0 голосов
/ 10 августа 2020

Я записываю решение только для этого одного случая. Как страхователь уже сказал вам, вы должны предоставить другие кейсы, если таковые имеются, и показать нам, что вы пробовали раньше. Скорее всего, это превратится в ад CASE WHEN, но я надеюсь, что приведенное ниже решение даст вам некоторое представление.

Решение

WITH MAIN
     AS (SELECT TO_DATE ('01012020', 'DDMMYYYY') AS Start_DATE,
                TO_DATE ('31012020', 'DDMMYYYY') AS End_Date,
                'S' AS config
           FROM DUAL
         UNION ALL
         SELECT TO_DATE ('15012020', 'DDMMYYYY') AS Start_DATE,
                TO_DATE ('20012020', 'DDMMYYYY') AS End_Date,
                'D' AS config
           FROM DUAL
         UNION ALL
         SELECT TO_DATE ('15022020', 'DDMMYYYY') AS Start_DATE,
                TO_DATE ('20022020', 'DDMMYYYY') AS End_Date,
                'D' AS config
           FROM DUAL
         UNION ALL
         SELECT TO_DATE ('01032020', 'DDMMYYYY') AS Start_DATE,
                TO_DATE ('20032020', 'DDMMYYYY') AS End_Date,
                'S' AS config
           FROM DUAL
        ),
     MAIN2
     AS (SELECT START_DATE AS DET FROM MAIN
         UNION
         SELECT END_DATE FROM MAIN),
     MAIN3
     AS (SELECT DET AS START_DATE,
                LEAD (DET, 1)
                   OVER (PARTITION BY TO_CHAR (DET, 'YYYYMM') ORDER BY DET)
                   AS END_DATE,
                  LEAD (DET, 1)
                     OVER (PARTITION BY TO_CHAR (DET, 'YYYYMM') ORDER BY DET)
                - 1
                   ED2,
                  LEAD (DET, 1)
                     OVER (PARTITION BY TO_CHAR (DET, 'YYYYMM') ORDER BY DET)
                + 1
                   ED3
           FROM MAIN2),
     MAIN4
     AS (SELECT *
           FROM MAIN3
          WHERE END_DATE IS NOT NULL),
     MAIN5
     AS (SELECT CASE
                   WHEN B.START_DATE IS NOT NULL
                   THEN
                      B.START_DATE
                   WHEN     B.START_DATE IS NULL
                        AND LAG (
                               A.START_DATE,
                               1)
                            OVER (
                               PARTITION BY TO_CHAR (A.START_DATE, 'YYYYMM')
                               ORDER BY A.START_DATE)
                               IS NOT NULL
                   THEN
                        LAG (
                           A.START_DATE,
                           1)
                        OVER (PARTITION BY TO_CHAR (A.START_DATE, 'YYYYMM')
                              ORDER BY A.START_DATE)
                      + 1
                   WHEN     B.START_DATE IS NULL
                        AND LAG (
                               A.START_DATE,
                               1)
                            OVER (
                               PARTITION BY TO_CHAR (A.START_DATE, 'YYYYMM')
                               ORDER BY A.START_DATE)
                               IS NULL
                   THEN
                      A.START_DATE
                END
                   START_DATE,
                CASE
                   WHEN B.END_DATE IS NOT NULL
                   THEN
                      B.END_DATE
                   WHEN     B.END_DATE IS NULL
                        AND LEAD (
                               A.END_DATE,
                               1)
                            OVER (PARTITION BY TO_CHAR (A.END_DATE, 'YYYYMM')
                                  ORDER BY A.START_DATE)
                               IS NOT NULL
                   THEN
                      A.END_DATE - 1
                   WHEN     B.END_DATE IS NULL
                        AND LEAD (
                               A.END_DATE,
                               1)
                            OVER (PARTITION BY TO_CHAR (A.END_DATE, 'YYYYMM')
                                  ORDER BY A.START_DATE)
                               IS NULL
                   THEN
                      A.END_DATE
                END
                   END_DATE,
                B.START_DATE ST,
                B.END_DATE ED,
                CASE WHEN B.CONFIG IS NOT NULL THEN B.CONFIG ELSE 'S' END
                   CONFIG
           FROM MAIN4 A
                LEFT JOIN MAIN B
                   ON B.START_DATE = A.START_DATE AND B.END_DATE = A.END_DATE --AND B.CONFIG='D'
                                                                             )
  SELECT START_DATE, END_DATE, CONFIG
    FROM MAIN5
ORDER BY 1

введите описание изображения здесь

...