2010-06-05 83 views
0

我必须确定停车时间,每隔30秒向服务器发回其状态数据,并将此数据存储在数据库的表中。SQL查询确定范围内的停止时间

状态记录的字段由(vehicleID,ReceiveDate,ReceiveTime,Speed,Location)组成。

现在我想要做的是,确定每个停车时间点,车辆速度为零,车辆再次移动的状态等等,以便下一次暂停时间。例如,在给定的一天,给定的车辆可能有10个停止状态,我必须通过查询确定每个车辆的持续时间。
结果可能是这样的:

id Recvdate Rtime Duration 
1 2010-05-01 8:30 45min 
1 2110-05-01 12:21 3hour 
+1

请发布您迄今为止编写的代码。人们通常不喜欢只为你写代码。 – 2010-06-05 05:44:31

+2

这很难做到。关于连续范围的这篇文章可能会帮助你在你的方式http://www.xaprb.com/blog/2006/03/22/find-contiguous-ranges-with-sql/ – 2010-06-05 14:12:55

+0

感谢百万马丁,这是非常有帮助的,我用本指南编写查询,谢谢。 每个人都想看到查询我可以把它放在这里 – sirvan 2010-06-07 06:46:43

回答

0

这是窗口函数(称为解析函数中的Oracle)的应用程序。

您的目标是为每个停靠点序列分配一个“块号”。也就是说,在一个序列中(车辆)的所有停止将具有相同的块编号,并且这将与所有其他停止序列不同。

下面是分配块数的方法:

  1. 创建速度标志,该标志表示1时速度> 0和0时速度= 0
  2. 枚举的所有记录,其中的速度标志= 1.这些是“块”。
  3. 做一个自加入,将每个标志= 0放入一个块(这需要分组并取最大的blocknum)。
  4. 按持续时间或无论你想要总结。

以下代码是我的意思的草图。它不会解决你的问题,因为你不清楚如何处理日间休息,你想要总结什么信息,并且它有一个错误的1错误(在每个停止序列中它包括前一个不停止的,如果有的话)。

with vd as 
(
    select vd.*, 
     (case when SpeedFlag = 1 
      then ROW_NUMBER() over (partition by id, SpeedFlag) end) as blocknum 
    from 
    (
     select vd.*, (case when speed = 0 then 0 else 1 end) as SpeedFlag 
     from vehicaldata vd 
    ) vd 
) 
select id, blocknum, COUNT(*) as numrecs, SUM(duration) as duration 
from 
(
    select vd.id, vd.rtime, vd.duration, MAX(vdprev.blocknum) as blocknum 
    from vd 
    left outer join vd vdprev 
    on vd.id = vdprev.id 
    and vd.rtime > vdprev.rtime 
    group by vd.id, vd.rtime, vd.duration 
) vd 
group by id, blocknum