2015-10-24 77 views
3

我有一個設備座標時間序列(timestamp,x,y,device_id)的數據庫。如何確定SQL中某個區域和時間範圍內多個設備上的最長駐留時間?如何確定幾何區域內的平均停留時間

這裏是我的數據的至(1.0,1.0的例子(注意,不是在有規律的間隔)

|   ts   | x | y | device_id 
---------------------+-----+-----+------------- 
2015-10-24 14:12:39 | 0.5 | 0.5 | 1 
2015-10-24 14:12:40 | 0.5 | 0.5 | 1 
2015-10-24 14:12:51 | 0.5 | 0.5 | 1 
2015-10-24 14:12:52 | 1.0 | 1.0 | 1 
2015-10-24 14:12:53 | 1.5 | 1.5 | 1 
2015-10-24 14:12:56 | 1.0 | 1.0 | 1 
2015-10-24 14:12:57 | 0.5 | 0.5 | 1 
2015-10-24 14:12:58 | 0.5 | 0.5 | 1 
2015-10-24 14:12:39 | 0.5 | 0.5 | 2 
2015-10-24 14:12:40 | 0.5 | 0.5 | 2 
2015-10-24 14:12:41 | 1.0 | 1.0 | 2 
2015-10-24 14:12:42 | 1.5 | 1.0 | 2 
2015-10-24 14:12:45 | 2.0 | 1.0 | 2 
2015-10-24 14:12:48 | 2.0 | 1.0 | 2 
2015-10-24 14:12:49 | 2.0 | 1.0 | 2 

在這裏,停留時間爲裝置1的區域內(0.0,0.0) )將是12秒(14:12:39到14:12:51)和1秒(14:12:57到14:12:58)。設備2在同一區域內的停留時間爲2秒(14:12:39至14:12:41)。最大值爲12s,最小值爲1s,平均值爲5s。

我最初的想法是將device_id上​​的數據進行分區以獲取每個設備的設置,然後確定min(ts)和max(ts)之間的持續時間作爲該設備的最長時間段,然後在使用以下內容作爲子查詢跨所有設備的期間。

SELECT (max(ts)-min(ts)) as longest_period, device_id 
FROM readings 
WHERE x < 1.0 AND x > 0.0 AND y < 1.0 AND y > 0.0 
GROUP BY device_id, ts 
+0

你如何定義一個區域? 'x'和'y'完全一樣嗎? –

+0

這是兩個設備在更大的區域內移動,表中的x和y是它們在任何給定時間的位置。總面積的大小(在我的情況下爲10.0x10.0)並不重要,因爲我只看到我定義的區域的一小部分(0.0,0.0)到(1.0,1.0) – codehugger

回答

3

當我在寫我開始以後我自己的想法和幾個網絡搜索擴大的問題和閱讀的Postgres文檔(這是真棒BTW;)我創建了下面的查詢,這似乎執行得很好並做我想做的事情。我承認這比我預料的要複雜一點。

select 
    hour, 
    (extract(epoch FROM max(t2.duration)))::int as max_dwell_time, 
    (extract(epoch FROM min(t2.duration)))::int as min_dwell_time, 
    (extract(epoch FROM avg(t2.duration)))::int as avg_dwell_time 
from 
    (
    select 
     t1.device_id, 
     date_trunc('hour', t1.ts) as hour, 
     sum(t1.duration) as duration 
    from 
     (
     select 
      distinct(ts), 
      device_id, 
      lag(ts) over (order by ts) as prev_ts, 
      ts - lag(ts) over (order by ts) as duration 
     from 
      spatial_readings 
     where 
      x < 10.0 and y < 10.0 
     order by device_id, ts 
    ) t1 
    where t1.duration < interval '60 second' 
    group by t1.device_id, date_trunc('hour', t1.ts) 
    order by t1.device_id 
) as t2 
group by hour 
order by hour; 

最內查詢(T1)確定使用postgres的窗口函數時間戳之間的間隙,中間查詢總結是小於由小時和設備60年代閾值和組中的所有的持續時間。最外面的查詢然後以秒爲單位提取最大,最小和平均停留時間並顯示每個小時。

下面是一個例子結果根據我的測試數據

hour     | max_dwell_time | min_dwell_time | avg_dwell_time 
---------------------+----------------+----------------+---------------- 
... 
2015-10-24 14:00:00 |    77 |    21 |    49 
2015-10-24 15:00:00 |   177 |   109 |   143 
2015-10-24 16:00:00 |    4 |    4 |    4 
2015-10-24 17:00:00 |    41 |    41 |    41 
2015-10-24 18:00:00 |    18 |    18 |    18 
... 
1

這似乎回答你的問題,至少在一臺設備和區域:

SELECT (max(ts)-min(ts)) as longest_period, device_id 
FROM readings 
WHERE x < 1.0 AND x > 0.0 AND y < 1.0 AND y > 0.0 
GROUP BY device_id 
ORDER BY longest_period DESC 
LIMIT 1; 

您可以輕鬆地添加任何限制你想要在ts以及。

+0

這查詢的工作原理,但它假定設備不會在區域外面並在所查看的時間範圍內返回。如果該設備在該區域存在1分鐘,然後離開30分鐘,然後再回來2分鐘,則最長停留時間爲2分鐘,但上述查詢將返回33分鐘,因爲在我的情況下,這是最長的停留時間。 – codehugger