有几种方法可以解决这个问题.一个使用相关子查询.那不是很有趣.相反,让我们使用累积和方法,因为你有Oracle.
关键是从一个时间戳列表开始,一个值为+1,一个开头为-1,结束时为-1.这很简单:
select t.*
from ((select starttime as thetime, 1 as value from table t) union all
(select endtime, -1 as value from table t)
) t
Run Code Online (Sandbox Code Playgroud)
现在,累积总和value告诉您在任何给定时间的活动重叠次数:
select t.*, sum(value) over (order by thetime) as numactives
from ((select starttime as thetime, 1 as value from table t) union all
(select endtime, -1 as value from table t)
) t
Run Code Online (Sandbox Code Playgroud)
这解决了您的问题.您可能想要order by numactives desc在特定时间添加一个.
这是一个使用简单自连接的示例解决方案,并且GROUP BY:
WITH d(id, t1, t2) AS (
SELECT 1, date '2010-01-01', date '2010-03-01' FROM DUAL UNION ALL
SELECT 2, date '2010-02-01', date '2010-04-01' FROM DUAL UNION ALL
SELECT 3, date '2010-02-01', date '2010-04-01' FROM DUAL UNION ALL
SELECT 4, date '2010-01-01', date '2010-01-03' FROM DUAL UNION ALL
SELECT 5, date '2011-01-01', date '2011-02-15' FROM DUAL
)
SELECT d1.id, d1.t1, d1.t2,
COUNT(*) "Overlap count",
LISTAGG('[' || d2.t1 || ', ' || d2.t2 || ']', ', ')
WITHIN GROUP (ORDER BY d2.id) "Overlapping intervals"
FROM d d1
LEFT OUTER JOIN d d2
ON d2.t1 <= d1.t2 AND d1.t1 <= d2.t2
GROUP BY d1.id, d1.t1, d1.t2
ORDER BY COUNT(*) DESC
Run Code Online (Sandbox Code Playgroud)
该"Overlapping intervals"聚合是仅用于说明.
...输出:
| ID | OVERLAP COUNT | OVERLAPPING INTERVALS |
|----|---------------|------------------------------------------------------------------------------------------------|
| 1 | 4 | [01-JAN-10, 01-MAR-10], [01-FEB-10, 01-APR-10], [01-FEB-10, 01-APR-10], [01-JAN-10, 03-JAN-10] |
| 2 | 3 | [01-JAN-10, 01-MAR-10], [01-FEB-10, 01-APR-10], [01-FEB-10, 01-APR-10] |
| 3 | 3 | [01-JAN-10, 01-MAR-10], [01-FEB-10, 01-APR-10], [01-FEB-10, 01-APR-10] |
| 4 | 2 | [01-JAN-10, 01-MAR-10], [01-JAN-10, 03-JAN-10] |
| 5 | 1 | [01-JAN-11, 15-FEB-11] |
Run Code Online (Sandbox Code Playgroud)