Java Oracle SQL-计算并发事件数

Java Oracle SQL-计算并发事件数,java,sql,oracle,Java,Sql,Oracle,我试图找出一种方法,可以识别表中的事件记录何时同时发生 例如,考虑在Oracle数据库中有一个名为“代码>事件< /代码>的表:: |EVENT_UUID|HOST_NAME|START_TM|END_TM| |1|host1|12-JUN-15 01.31.04.092000000 PM|12-JUN-15 01.55.58.716000000 PM| |2|host2|15-JUN-15 10.02.45.494000000 AM|15-JUN-15 01.12.18.257000000

我试图找出一种方法,可以识别表中的事件记录何时同时发生

例如,考虑在Oracle数据库中有一个名为“代码>事件< /代码>的表::

|EVENT_UUID|HOST_NAME|START_TM|END_TM|

|1|host1|12-JUN-15 01.31.04.092000000 PM|12-JUN-15 01.55.58.716000000 PM|
|2|host2|15-JUN-15 10.02.45.494000000 AM|15-JUN-15 01.12.18.257000000 PM|
|3|host3|17-JUN-15 03.19.48.506000000 PM|17-JUN-15 03.51.59.874000000 PM|
|4|host4|18-JUN-15 09.24.36.602000000 PM|NULL|
|5|host5|18-JUN-15 12.32.43.109000000 PM|19-JUN-15 01.22.32.412000000 PM|
我知道我可以通过这样做找到在给定日期范围内开始的所有事件::

SELECT *
FROM EVENTS
WHERE START_TM BETWEEN TO_DATE('2015-JUN-11', 'YYYY-MON-DD') AND TO_DATE('2015-JUN-13', 'YYYY-MON-DD');
但这只给了我在这个范围内开始的所有事件

最终,我希望能够运行报告并检查以下内容

  • “一天内发生的并发事件数。”
  • “一小时内发生的并发事件数。”

有人知道有什么方法可以帮助我识别事件何时同时发生吗?

使用类似于以下内容的谓词:

where start_tm <= TO_DATE('2015-JUN-13 23:59:59', 'YYYY-MON-DD HH24:MI:SS')
  and (end_tm is null or TO_DATE('2015-JUN-11 00:00:00', 'YYYY-MON-DD HH24:MI:SS') <= end_tm)

where start_tm我认为您需要将表本身连接起来,并获取所有事件,其中包含两个事件:

event1.start between event2.start and event2.end 
OR
event1.end   between event2.start and event2.end 
OR
event1.start < event2.start and event1 > event2.end
AND CHECK THAT
event.end can be null

to filter the data - see `where` in query below
to count number of events - use count(*) over ()
查询:

select ev1.event_uuid, ev2.event_uuid
     , ev1.start_tm, ev1.end_tm
     , ev2.start_tm, ev2.end_tm
     ,count(*) over () as total_count
 from events ev1
  inner join events ev2
    on ((ev1.start_tm between ev2.start_tm and nvl(ev2.end_tm, sysdate))
     or (nvl(ev1.end_tm,sysdate) between ev2.start_tm and nvl(ev2.end_tm, sysdate))
     or (ev2.start_tm < ev1.start_tm and nvl(ev1.end_tm,sysdate) < nvl(ev1.end_tm, sysdate)))
        and ev1.event_uuid != ev2.event_uuid
  where to_date('18.06.2015 13', 'dd.mm.yyyy hh24') between  ev1.start_tm and nvl(ev1.end_tm,sysdate)
order by 3,4   

    EVENT_UUID  EVENT_UUID  START_TM    END_TM  START_TM    END_TM  TOTAL_COUNT
1   5   4   18/06/2015 12:32:43 19/06/2015 01:22:32 18/06/2015 09:24:36     3
2   6   5   18/06/2015 12:45:43 19/06/2015 01:01:32 18/06/2015 12:32:43 19/06/2015 01:22:32 3
3   6   4   18/06/2015 12:45:43 19/06/2015 01:01:32 18/06/2015 09:24:36     3
选择ev1.event\u uuid、ev2.event\u uuid
,ev1.start_tm,ev1.end_tm
,ev2.start_tm,ev2.end_tm
,计数(*)超过()作为总计数
来自事件ev1
内部连接事件ev2
on((ev2.start_tm和nvl之间的ev1.start_tm(ev2.end_tm,系统日期))
或者(ev2.start_tm和nvl(ev2.end_tm,sysdate)之间的nvl(ev1.end_tm,sysdate))
或者(ev2.start_tm
您可以使用一种相对简单的技术来计算并发事件的数量:累积聚合。这个想法是计算启动和停止的次数。那么,累积数就是并发值的数目

select tm, sum(isstart) as numstarts, sum(isstop) as numstops,
       (sum(sum(isstart)) over (order by tm nulls last) -
        sum(sum(isstop)) over (order by tm nulls last)
       ) as NumConcurrent
from ((select start_tm as tm, 1 as isstart, 0 as isstop from events
      ) union all
      (select stop_tm, 0 as isstart, 1 as isstop from events
      )
     ) e
group by tm;

这将为您提供数据中每次并发事件的数量(开始时间或结束时间。然后,您可以使用
where
子句和
order by
/
fetch first
或aggregation提取一天或一小时的最大值。

这可能是关于日期重叠的最佳解释
NULL
对于
end_TM
意味着什么?@ShannonSeverance它意味着什么事件尚未结束。这些事件基本上表示用户许可证的消耗量,我希望跟踪在任何给定时间消耗的许可证数量。在OP的数据中,时间部分包括AM/PM指定。您在转录示例数据时删除了这些指定,使事件2在开始之前结束。感谢但他发布了Gordon.问题。出于某种原因,当我运行您的示例时,我得到的记录的START_TM值在数据库中实际上不存在。
“TM”“NUMSTARTS”“NUMSTOPS”“NUMCONCURRENT”12-JUN-15 11.16.42.811000000 AM 200 2 12-JUN-15 11.17.15.001000000 AM 200 4 12-JUN-15 12.01.30.957000000 PM 200 6 12-JUN-15 12.07.55.972000000 PM 02 4 12-JUN-15 12.51.57.551000000 PM 02 12-JUN-15 01.27.01.938000000 PM 200 4 12-JUN-15 01.30.45.121000000 PM 200 6
关于如何发生的任何想法?我将在下一篇文章中发布我写的SQL注释。限制我的是:
选择tm,sum(isstart)作为numstarts,sum(isstop)作为numstops,(sum(sum(isstart))over(order by tm nulls last)-sum(sum(isstop))over(order by tm nulls last))作为NumConcurrent from((选择e1.START_tm作为tm,1作为isstart,0作为isstop from EVENTS e1)union all(从事件e2中选择e2.END_TM,0作为isstart,1作为isstop),其中TM介于至日期('2015-6-11','YYYY-MON-DD')和至日期('2015-6-13','YYYY-MON-DD')之间这是一项非常有趣的技术。我不容易得到,但我喜欢。@Chiefwarpaint…这是正确的。这会为每次开始和停止时间生成一个记录。每当它们发生变化时,它都会有并发计数。@GordonLinoff再次感谢您的帮助。也许我是完全密集的,但我仍然不明白查询是如何将START_TM等于数据库中不存在的值的记录拉回来的。也许在这个SQL中出现了一些我没有的隐含算法?
select tm, sum(isstart) as numstarts, sum(isstop) as numstops,
       (sum(sum(isstart)) over (order by tm nulls last) -
        sum(sum(isstop)) over (order by tm nulls last)
       ) as NumConcurrent
from ((select start_tm as tm, 1 as isstart, 0 as isstop from events
      ) union all
      (select stop_tm, 0 as isstart, 1 as isstop from events
      )
     ) e
group by tm;