Oracle запрос, чтобы найти разрыв в нескольких циклах дат - PullRequest
0 голосов
/ 09 июля 2019

Как мы могли видеть, у нас есть несколько циклов для одной и той же комбинации клиента и контракта, но существует разрыв между одной датой окончания цикла и другой датой начала цикла.

Я хотел бы найти все те комбинации клиентов и контрактов в моей таблице, в которых есть разрыв для нескольких циклов. Не обязательно завершать последний цикл. Дата окончания по умолчанию может быть 01/01/3000, что означает, что цикл все еще активен.

Может кто-нибудь помочь мне с запросом?

Customer_ID   Contract_Id     Start_Date    End_Date
1                 21          01/01/2018   02/01/2018
1                 21          02/06/2018   03/01/2018

Ответы [ 2 ]

2 голосов
/ 09 июля 2019

Я думаю, что вы можете использовать аналитическую функцию LEAD, чтобы получить дату начала следующего цикла, а затем сравнить ее с датой окончания периода:

create table contracts (
    Customer_ID     number,
    Contract_Id     number,
    Start_Date      date,
    End_Date        date
);


-- with gap
insert into contracts values (1, 21, to_date('01/01/2018','MM/DD/YYYY') , to_date('02/01/2018','MM/DD/YYYY'));
insert into contracts values (1, 21, to_date('02/06/2018','MM/DD/YYYY'), to_date('03/01/2018','MM/DD/YYYY'));
-- no gap (next start_date = end_date+1)
insert into contracts values (2, 21, to_date('01/01/2018','MM/DD/YYYY') , to_date('02/01/2018','MM/DD/YYYY'));
insert into contracts values (2, 21, to_date('02/02/2018','MM/DD/YYYY'), to_date('03/01/2018','MM/DD/YYYY'));
-- with gap. no end date
insert into contracts values (3, 21, to_date('01/01/2018','MM/DD/YYYY') , to_date('02/01/2018','MM/DD/YYYY'));
insert into contracts values (3, 21, to_date('02/06/2018','MM/DD/YYYY'), null);
-- no gap, no end date
insert into contracts values (4, 21, to_date('01/01/2018','MM/DD/YYYY') , to_date('02/01/2018','MM/DD/YYYY'));
insert into contracts values (4, 21, to_date('02/02/2018','MM/DD/YYYY'), null);
-- one period
insert into contracts values (5, 21, to_date('01/01/2018','MM/DD/YYYY') , to_date('02/01/2018','MM/DD/YYYY'));
-- one period, no end date
insert into contracts values (6, 21, to_date('01/01/2018','MM/DD/YYYY') , null);
commit;

select customer_id, contract_id, start_date, end_date, next_start_date, (next_start_date-end_date) as gap 
from (
    select customer_id, contract_id, start_date, end_date, 
            lead(start_date, 1, end_date+1) over (partition by customer_id, contract_id order by start_date) next_start_date
        from contracts
) 
where next_start_date != end_date + 1;

CUSTOMER_ID CONTRACT_ID START_DAT END_DATE  NEXT_STAR        GAP
----------- ----------- --------- --------- --------- ----------
          1          21 01-JAN-18 01-FEB-18 06-FEB-18          5
          3          21 01-JAN-18 01-FEB-18 06-FEB-18          5
1 голос
/ 10 июля 2019

Этого также можно добиться с помощью самостоятельного соединения.

Я попытался решить эту проблему с помощью самостоятельного соединения следующим образом:

-- GAP IN PERIOD
SELECT
    C1.CUSTOMER_ID,
    C1.CONTRACT_ID,
    C1.START_DATE   AS START_DATE,
    C1.END_DATE     AS END_DATE,
    C2.START_DATE - C1.END_DATE AS GAP,
    C2.START_DATE   AS NEXT_START_DATE
FROM
    CONTRACTS C1
    JOIN CONTRACTS C2 ON ( C1.CUSTOMER_ID = C2.CUSTOMER_ID
                           AND C1.CONTRACT_ID = C2.CONTRACT_ID
                           AND C2.START_DATE > C1.START_DATE
                           AND C2.START_DATE - C1.END_DATE <> 1 
                           AND C2.START_DATE - C1.END_DATE > 0) -- ADDED THIS CONDITION

Примечание. При нахождении перекрывающихся циклов яобнаружена проблема в текущем коде, и она устранена - последнее условие

Вывод:

enter image description here

db <> fiddle demo

Примечание: я использовал те же данные из предыдущего ответа.

Cheers !!

-

Обновлено

Запрос на поиск цикла перекрытия:

-- OVERLAPPING IN PERIOD

SELECT
    C1.CUSTOMER_ID,
    C1.CONTRACT_ID,
    C1.START_DATE   AS START_DATE,
    C1.END_DATE     AS END_DATE,
    C2.START_DATE - C1.END_DATE AS GAP,
    C2.START_DATE   AS NEXT_START_DATE
FROM
    CONTRACTS C1
    JOIN CONTRACTS C2 ON ( C1.CUSTOMER_ID = C2.CUSTOMER_ID
                           AND C1.CONTRACT_ID = C2.CONTRACT_ID
                           AND C2.START_DATE > C1.START_DATE
                           AND C2.START_DATE - C1.END_DATE <> 1 
                           AND C2.START_DATE - C1.END_DATE < 0)

Вывод:

enter image description here

обновленная демо-версия db <> fiddle

Cheers !!

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