2010-06-05 123 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