【问题标题】:SQL query determine stopped time in a rangeSQL查询确定范围内的停止时间
【发布时间】:2011-02-28 02:07:48
【问题描述】:

我必须确定每 30 秒将其状态数据发送回服务器的车辆的停止时间,并且该数据存储在数据库的表中。

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

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

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

【问题讨论】:

  • 请贴出你目前写的代码。人们通常不喜欢只为您编写代码。
  • 这很难做到。这篇关于连续范围的文章可能会对您有所帮助xaprb.com/blog/2006/03/22/find-contiguous-ranges-with-sql
  • 感谢一百万马丁,这非常有帮助,我使用本指南编写查询,谢谢。大家想看的查询我可以放在这里

标签: sql mysql database


【解决方案1】:

这是一个windows函数的应用(在Oracle中称为分析函数)。

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

这是分配块号的一种方法:

  1. 创建一个速度标志,当速度 > 0 时显示为 1,当速度 = 0 时显示为 0。
  2. 枚举所有速度标志 = 1 的记录。这些是“块”。
  3. 执行自连接以将每个标志 = 0 放入一个块中(这需要分组并获取最大块数)。
  4. 按持续时间或根据需要进行汇总。

以下代码是我的意思的草图。它不会解决你的问题,因为你不清楚如何处理休息日,你想总结什么信息,并且它有一个 off-by-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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 2021-11-15
    • 2023-03-03
    相关资源
    最近更新 更多