找到两组日期范围之间的重叠

find overlap between two sets of date ranges

我想使用 Oracle SQL 或 PL/SQL.

找出每个订单号的两组日期范围之间的重叠

输入是“结果集一”和“结果集二”。输出应该是“重叠”。

结果集一

WITH T_RESULT_SET_ONE as(
select 21365 order_number,to_date('01/01/2021 09:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 10:30:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21365 order_number,to_date('02/01/2021 14:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('02/01/2021 18:00:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21367 order_number,to_date('01/01/2021 08:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 09:43:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21367 order_number,to_date('01/01/2021 16:34:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 18:15:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
union
select 21367 order_number,to_date('04/01/2021 15:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('04/01/2021 16:15:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
)

结果集二

T_RESULT_SET_TWO as(
select 21365 order_number,to_date('01/01/2021 09:30:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 09:45:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21365 order_number,to_date('02/01/2021 13:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('02/01/2021 17:00:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
union
select 21367 order_number,to_date('01/01/2021 09:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 10:00:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21367 order_number,to_date('01/01/2021 16:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 19:00:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21367 order_number,to_date('05/01/2021 19:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('04/01/2021 19:46:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
)

重叠

T_OVERLAP as
(
select 21365 order_number,to_date('01/01/2021 09:30:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 09:45:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
union
select 21365 order_number,to_date('02/01/2021 14:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('02/01/2021 17:00:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
union
select 21367 order_number,to_date('01/01/2021 09:00:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 09:43:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
UNION
select 21367 order_number,to_date('01/01/2021 16:34:00', 'DD/MM/YYYY HH24:MI:SS') start_date_time, to_date('01/01/2021 18:15:00', 'DD/MM/YYYY HH24:MI:SS') finish_date_time FROM DUAL
)

下图说明了我要执行的操作(日期范围与我之前提供的不一样)

任何人都可以提供 SQL 查询或 PL/SQL 程序吗?

看来你要找的不是INTERSECT而是重叠的。在Oracle中intersect一般指2个查询的共同结果:

Select <columns list> from table1
INTERSECT
Select <columns list> from table2;

其中列列表具有相同的定义并且结果值相同。您正在寻找的是值彼此重叠的位置,而不是行包含相同值的位置。
让我们考虑 2 个事件调用 'A' 和 'B',重叠的可能性有 4 种:

  1. A开始,B开始,B结束,A结束。 A完全重叠B.
  2. A开始,B开始,A结束,B结束。 A 重叠 B
  3. 的开头
  4. B开始,A开始,B结束,A结束。 A 与 B
  5. 的结尾重叠
  6. B开始,A开始,A结束,B结束。 A与B完全重叠。

解析只是确定,就是需要确定我们取最大开始时间和最小结束时间的重叠。使用您提供的数据,这只需要上述其中一项:

select order_number
     , greatest(t1start, t2start) start_date_time
     , least(t1finish,t2finish) finish_date_time     
 from ( select t1.order_number
             , t1.start_date_time   t1start
             , t1.finish_date_time  t1finish
             , t2.start_date_time   t2start
             , t2.finish_date_time  t2finish             
          from t_result_set_one t1
          join t_result_set_two t2
            on t1.order_number = t2.order_number 
         where (    t1.finish_date_time >= t2.start_date_time
                and t1.start_date_time  <= t2.finish_date_time
               ) 
      );    

参见fiddle here。我给你留下其他3种可能性。