Oracle查询以找出多个日期周期中的差距

时间:2019-07-09 20:19:20

标签: oracle

我们可以看到,对于同一个客户和合同组合,我们有多个周期,但是一个周期的结束日期与另一个周期的开始日期之间存在差距。

我想在我的表中找到所有存在多个周期缺口的客户和合同组合。不一定要结束最新周期。它的默认结束日期可以为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 个答案:

答案 0 :(得分:2)

我认为您可以使用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 :(得分:1)

您也可以通过使用自联接来实现此目的。

我尝试使用自连接解决以下问题:

-- 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

注意:我已经使用了上一个答案中的相同数据。

干杯!

-

已更新

查询以查找重叠周期:

-- 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

updated db<>fiddle demo

干杯!