2016-01-28 54 views
0

我有一組機器。他們偶爾跑步和停止。這些運行時間自動記錄到postgres表中,時間戳starttimeendtime重疊時間框架的SQL解決方案

我需要在6小時內找到每臺機器的運行時間。這是我到目前爲止:

SELECT machine, SUM(EXTRACT(EPOCH FROM (endtime - starttime))) 
FROM table 
WHERE 
     starttime >= '2016-01-27 12:00:00' 
     AND starttime <= '2016-01-27 18:00:00' 
GROUP BY machine 
ORDER BY machine 

所以這個工程,我得到的機器在該時間段內運行時間秒。但它有一個缺陷 - 在12:00之前開始的任何運行時間都不計算在內。而且任何運行時間都是在我的時間框架內開始的,但不會在計算完時間之後纔會結束,而這些時間不應該在那裏。

是否有解決方案只提取時間範圍內的時間?我最初的想法是選擇所有行:

endtime >= '2016-01-27 12:00:00' 

,不管怎樣,在內存中,在'2016-01-27 12:00:00' 設置所有的開始時間,其中開始時間比更早:

starttime <='2016-01-27 18:00:00' 

和,再次在內存中而不更新數據庫,將所有結束時間設置爲'2016-01-27 18:00:00',其中結束時間晚於結束時間。然後運行提取/求和查詢。

但我正在努力如何實現這樣的事情。我有一個Java/Python的工作解決方案,這個數據被返回,但它們是迭代的,比我想要的要多。如果可能的話,我真的很想找到一個SQL解決方案。

編輯:爲了澄清,我需要計數該發生的時間框架內 ALL運行時間 - 如果一個運行的時間幀出現的時間幀應當被計數後運行僅部分之前開始。

+0

只需啓動在ts1和ts2之間或在ts1和ts2之間結束? – jarlh

+0

是不是每次都在這些時間之間? – Takarii

+0

@Takarii否,時間範圍由用戶指定。 jarlh這會在開始和結束的時候計算短時間 - 我需要計算在此時間範圍內發生的所有運行時間,而不管它何時開始或停止。 –

回答

1

編輯:這是你所需要的。

當它在範圍之間開始,並在其後結束時,它將計算結束於18:00:00。

同去當擋位之間結束前開始,它會計算值,因爲它開始於12:00:00

SELECT machine, SUM(EXTRACT(EPOCH FROM (endtime - starttime))) 
FROM (SELECT machine, 
      case when starttime <= '2016-01-27 12:00:00' then '2016-01-27 12:00:00' else starttime end as starttime, 
      case when endtime>= '2016-01-27 18:00:00' then '2016-01-27 18:00:00' else endtime end as endtime, FROM table 
    WHERE 
      (endtime>= '2016-01-27 12:00:00' 
      AND endtime <= '2016-01-27 18:00:00') 
      OR (starttime>= '2016-01-27 12:00:00' 
      AND starttime<= '2016-01-27 18:00:00') 
GROUP BY machine 
ORDER BY machine 
+0

問題是如果運行在時間段之前開始,我需要計算在我的時間範圍內運行的部分。但不是時間表開始之前的部分。在結局方面相同 - 只有在時間範圍內運行的部分應該計算在內。 –

+0

仍然有困難的理解,你只希望那些誰開始和結束的時間?或那些只在時間表結束的人?要麼...?說這樣,我會寫在代碼@ErikN – sagi

+0

因此,如果我的開始時間是''2016-01-27 12:00:00'',如果我有一個運行開始於''2016-01 -27 11:55:00''並於'2016-01-27 12:05:00'結束,應該只添加5分鐘。同樣如果我的結局時間是''2016-01-27 18:00:00'',並且我有一個以'2016-01-27 17:55:00'開始的結果,並以' '2016-01-27 18:05:00'這也只會增加5分鐘。 –

1

可以使用重疊操作:

SELECT machine, SUM(EXTRACT(EPOCH FROM (endtime - starttime))) 
FROM table 
where (starttime, endtime) overlaps (timestamp '2016-01-27 12:00:00', timestamp '2016-01-27 18:00:00') 
GROUP BY machine 
ORDER BY machine 
1

使用類型tsrange及其intersection運營商。

實施例的數據:

create table machines (machine int, starttime timestamp, endtime timestamp); 
insert into machines values 
(1, '2016-01-27 10:00:00', '2016-01-27 14:00:00'), 
(2, '2016-01-27 15:00:00', '2016-01-27 16:00:00'), 
(3, '2016-01-27 17:00:00', '2016-01-27 20:00:00'); 

該查詢返回的時間框架四捨五入到給定的時間段:

select 
    machine, 
    tsrange(starttime, endtime)* 
     '[2016-01-27 12:00:00, 2016-01-27 18:00:00)'::tsrange t 
from machines; 

machine |      t      
---------+----------------------------------------------- 
     1 | ["2016-01-27 12:00:00","2016-01-27 14:00:00") 
     2 | ["2016-01-27 15:00:00","2016-01-27 16:00:00") 
     3 | ["2016-01-27 17:00:00","2016-01-27 18:00:00") 
(3 rows)  

獲得從上述數據集的骨料:

select 
    machine, 
    sum(extract(epoch from (upper(t) - lower(t)))) 
from (
    select 
     machine, 
     tsrange(starttime, endtime)* 
      '[2016-01-27 12:00:00, 2016-01-27 18:00:00)'::tsrange t 
    from machines 
    ) sub 
group by 1 
order by 1; 

machine | sum 
---------+------ 
     1 | 7200 
     2 | 3600 
     3 | 3600 
(3 rows)