我有两个表,分别是客户合同周期表和客户合同地点周期表。
客户合同周期表(PARENT表1)
ID Customer_ID Contract_ID START_DATE END_DATE
5215436 128 569 2/1/2015 6/25/2017
客户合同定位周期表(CHILD表2)
ID Customer_ID Client_ID LOCATION_ID CUSTOMER_CONTRACT_CYCLE_ID START_DATE END_DATE
37361952 128 284187 3477623 5215436 2/1/2015 12/31/2016
112243088 128 284187 3477623 5215436 1/1/2017 6/25/2017
表1中的ID列是表2中的外键,因为CUSTOMER_CONTRACT_CYCLE_ID列是
在我的示例中,单个客户合同有两个客户合同定位周期,而两个(Customer_ID, Client_ID, LOCATION_ID, CUSTOMER_CONTRACT_CYCLE_ID)
覆盖了整个客户合同周期。父子周期之间没有间隙,并且多个子周期涵盖了整个客户合同周期。但是我想找出那些客户合同定位周期,这些周期不能完全涵盖给定(Customer_ID, Client_ID, LOCATION_ID, CUSTOMER_CONTRACT_CYCLE_ID)
的客户合同周期。
答案 0 :(得分:0)
您需要查找四种情况:
以下查询搜索所有四种情况:
with
s (id, start_date, end_date, ls, le, prev_end, next_start) as (
select
c.id,
l.start_date,
l.end_date,
lag(end_date) over(partition by c.id order by l.start_date),
lead(start_date) over(partition by c.id order by l.start_date)
from customer_contract_cycles c
left join customer_contract_location_cycles l
on c.id = l.customer_contract_cycle_id
)
select 'no locations at all for the cycle' as message, id, start_date, end_date
from s
where ls is null or le is null
union all
select 'no location at start of cycle', id, start_date, end_date
from s
where prev_end is null and le <> start_date
union all
select 'no location at end of cycle', id, start_date, end_date
from s
where next_start is null and le <> end_date
union all
select 'no location in middle of cycle', id, start_date, end_date
from s
where next_start is not null and next_start <> le + 1
答案 1 :(得分:0)
从经验上讲:如果有机会,请重新定义end_date
。
在您的示例中,end_date
是12月31日,下一个start_date
是januari 1日。实际上,有两个日期表示 :第一个客户合同定位周期一直持续到第31个整个 12月,所以直到januari 1日?
在使用start
+ end
定义期间时,如果将end_date
定义为紧随实际结束时间,它将使计算和过滤更加容易。
有时使用[start_date, end_date[
表示法:句点中未包含end_date
。
这样设置数据后,您只需执行where previous.end_date = next.start_date
。这也使您可以使用简单的索引(而不是end_date+1
上基于函数的索引)。
一种替代方法是了解 Interval数据类型。通过定义,它定义了时间长度:使用start_date
字段和duration
字段而不是start_date, end_date
。
减去日期,例如next.start_date - previous.start_date
会返回一个间隔,因此您可以在next.start_date-previous.start_date <= prevous.duration
上进行过滤。
我想教给您的是,对数据进行不同的建模可以使以后的编程变得容易得多。