计算多个日期范围内有多少个重叠日期

Posted

技术标签:

【中文标题】计算多个日期范围内有多少个重叠日期【英文标题】:Calculate How Many Overlapping Dates There Are Within Multiple Date Ranges 【发布时间】:2021-07-14 00:17:18 【问题描述】:

我需要能够计算某人服用至少一种 A 类药物和 1 种 B 类药物的天数。

我遇到的最大问题之一是同一药物类别的处方可能会相互重叠,当它们加入 B 类处方时,我最终会重复计算天数。

例如,在 21 年 1 月 1 日到 21 年 6 月 30 日之间,每个人服用 A 类和 B 类药物的总天数是多少

下面我以假数据为例。

表 1

| ID | START | END | CLASS |
|:---- |:------| :-----| :-----|
|1234   |12-Feb-21  |19-Feb-21| A
|1234   |20-Feb-21  |22-Feb-21| A
|1243   |13-Mar-21  |23-Mar-21| A
|1234   |21-Apr-21  |1-May-21   |A
|1234   |20-Jun-21  |25-Jun-21  |A
|1234   |11-Jul-21  |16-Jul-21  |A
|4321   |25-Jan-21  |24-Feb-21  |A
|4321   |31-Jan-21  |2-Mar-21   |A
|4321   |28-Feb-21  |30-Mar-21  |A
|4321   |25-Mar-21  |24-Apr-21  |A
|4321   |25-Mar-21  |24-Apr-21  |A
|4321   |25-Apr-21  |25-May-21  |A
|4321   |29-Apr-21  |29-May-21  |A
|4321   |23-May-21  |22-Jun-21  |A
|4321   |26-May-21  |25-Jun-21  |A
|4321   |23-Jun-21  |23-Jul-21  |A
|4321   |23-Jun-21  |23-Jul-21  |A

表 2

| ID | START | END | CLASS |
|:---- |:------| :-----| :-----|
|1234   |18-Jan-21  |17-Feb-21  |B
|1234   |17-Mar-21  |16-Apr-21  |B
|1234   |14-Apr-21  |14-May-21  |B
|1234   |12-May-21  |11-Jun-21  |B
|1234   |9-Jun-21   |9-Jul-21   |B
|1234   |11-Jul-21  |10-Aug-21  |B
|4321   |25-Jan-21  |24-Feb-21  |B
|4321   |11-Feb-21  |13-Mar-21  |B
|4321   |7-Mar-21   |6-Apr-21   |B
|4321   |4-Apr-21   |4-May-21   |B
|4321   |30-Apr-21  |30-May-21  |B
|4321   |24-May-21  |23-Jun-21  |B
|4321   |20-Jun-21  |20-Jul-21  |B

PS - 我在 Oracle SQL Developer 工作

【问题讨论】:

【参考方案1】:

一种相对简单的方法是蛮力方法。这会将每个class 的时间段分成几天。然后加入并聚合得到总数:

with cte1(id, d, endd, class) as (
      select id, startd, endd, class
      from table1
      union all
      select id, d + interval '1' day, endd, class
      from cte1
      where d < endd
     ),
     cte2(id, d, endd, class) as (
      select id, startd, endd, class
      from table2
      union all
      select id, d + interval '1' day, endd, class
      from cte2 -- edit here
      where d < endd
     )
select cte1.id, count(*)
from cte1 join
     cte2
     on cte1.id = cte2.id and cte1.d = cte2.d
group by cte1.id;

Here 是一个 dbfiddle。

【讨论】:

在形成 cte2 时,它会错误地联合到 cte1,因此会产生不正确的结果。正确的结果是 36(来自 dbfiddle 的示例数据) 我编辑了答案,因为它只是一个错字,请原谅我 @PaulMaxwell 。 . .我还更换了 dbfiddle.

以上是关于计算多个日期范围内有多少个重叠日期的主要内容,如果未能解决你的问题,请参考以下文章

计算日期范围的重叠数量

SQL 重叠日期范围

如果我们有很多任务并且每个任务的日期范围可能重叠,如何计算任务的工作天数

PHP:选择时间范围重叠日期的重叠日期时间范围

PL/SQL:在由开始和结束定义的重叠日期范围内查找孤岛

Java日期时间API系列37-----时间段是否有重叠(交集)的计算方法