2014-01-21 54 views
1

我有一個postgresql 9.1表,其中包含開始和結束時間戳,記錄用戶標識可能重疊的時間段。例如:如何計算postgresql中多個記錄的開始和結束時間戳之間的總時間

Userid Begin      End 
1  2014-01-19 21:14:59+00 2014-01-19 21:30:00+00 
2  2014-01-19 21:19:29+00 2014-01-19 21:40:30+00 
1  2014-01-19 21:16:29+00 2014-01-19 21:31:30+00 
3  2014-01-19 21:15:22+00 2014-01-19 21:30:29+00 
2  2014-01-19 21:29:59+00 2014-01-19 21:45:00+00 
3  2014-01-19 21:15:25+00 2014-01-19 21:35:10+00 
4  2014-01-19 22:00:01+00 2014-01-19 22:05:20+00 

我需要得到每個用戶ID的所有分的總和在這些行確保時間不被重複計算的個人用戶標識,從而使輸出將是:

Userid Hour  Total Minutes 
1  21  n 
2  21  n 
3  21  n 
4  22  n 
+0

使用'tzrange'的'+'(範圍聯合)運算符對此會很有趣。很遺憾,它不支持不連續性;這讓我停止玩它變得更加困難。 –

回答

1

這是一個難題,但至少Postgres具有lag()的功能。

這是想法。假設你有重疊。找到沒有重疊的第一個元素。給它一個1的標誌值。然後做一個這個值的累計和。結果是,不同的時間段現在根據它們的「島嶼」被分配值。然後簡單的聚合工作。

下面將在許多情況下工作,使用lag()

select userid, sum(secs)/60 as minutes 
from (select userid, Island, min(begin) as begin, max(end) as end, 
      extract(epoch from max(end) - min(begin)) as secs 
     from (select t.*, 
        sum(IslandBegin) over (partition by userid order by begin) as Island 
      from (select t.*, 
         (case when lag(end) over (partition by userid order by begin) >= begin 
           then 0 
           else 1 
          end) as IslandBegin 
        from table t 
       ) t 
      ) t 
     group by userid, Island 
    ) t 
group by userid; 

注意end是一個保留字,所以相應地調整代碼。

以上並不總是有效。它假定重疊是與之前的開始相同的,可能並非如此。考慮{(1,100),(2,5),(8,10)}。我認爲正確的邏輯仍然需要相關的子查詢。最裏面的查詢需要從改變:

  from (select t.*, 
         (case when lag(end) over (partition by userid order by begin) >= begin 
           then 0 
           else 1 
          end) as IslandBegin 
        from table t 
       ) t 

到:

  from (select t.*, 
         coalesce((select 1 
            from table t2 
            where t2.end >= t.begin and 
             t2.begin < t.begin 
            limit 1 
           ), 0 
           ) as IslandBegin 
        from table t 
       ) t 

其實,這是沒有那麼糟糕,我瞭解到,lag()不能用於所有這樣的情況。

+0

在將表名更改爲活動表後,在嘗試此代碼時,它返回列(15)「isbegin」不存在。我將它改爲IslandBegin並重新開始。它回來了:'一個子查詢返回多個行作爲表達式' – Steve

+0

@Steve。 。 。那應該是'IslandBegin'。 –

+0

將'tzrange'和它的'+'運算符合併到這裏可能會很有趣。 –

相關問題