2015-06-03 22 views
9

我有PostgreSQL數據庫中約1萬個事件是這種格式:在巨大的事件流中發現差距?

id  | stream_id  | timestamp 
----------+-----------------+----------------- 
1   | 7    | .... 
2   | 8    | .... 

有大約50,000獨特的流。

我需要找到所有事件之間的任何兩個事件之間的時間超過一定的時間段。換句話說,我需要在一定時間內找到沒有事件的事件對。

例如:

a b c d e  f    g   h i j k 
| | | | |  |    |   | | | | 

       \____2 mins____/ 

在這種情況下,我想找到對(F,G),因爲這些是直接圍繞間隙的事件。

我不在乎查詢是否緩慢,即100萬條記錄,如果需要一個小時左右就沒有問題。但是,數據集將保持增長,所以希望如果速度緩慢的話,它可以保持穩定。

我也有MongoDB中的數據。

執行此查詢的最佳方式是什麼?

+0

事件是由單個時間點(而不是時間跨度)定義的嗎? –

+0

你想要每個流?換句話說,差距在屬於單一流的事件之間? – Patrick

+0

@MOehm是的,單個時間點 – MikeC8

回答

4

您可以通過按時間戳排序的stream_id在分區上使用lag()窗口函數執行此操作。 lag()函數可讓您訪問分區中的前幾行;沒有滯後值,這是前一行。因此,如果stream_id上的分區按時間排序,則前一行是該stream_id的上一個事件。

SELECT stream_id, lag(id) OVER pair AS start_id, id AS end_id, 
     ("timestamp" - lag("timestamp") OVER pair) AS diff 
FROM my_table 
WHERE diff > interval '2 minutes' 
WINDOW pair AS (PARTITION BY stream_id ORDER BY "timestamp"); 
4

在postgres中,它可以通過lag()窗口函數的幫助很容易地完成。檢查下面的撥弄爲例:

SQL Fiddle

的PostgreSQL 9.3架構設置

CREATE TABLE Table1 
    ("id" int, "stream_id" int, "timestamp" timestamp) 
; 

INSERT INTO Table1 
    ("id", "stream_id", "timestamp") 
VALUES 
    (1, 7, '2015-06-01 15:20:30'), 
    (2, 7, '2015-06-01 15:20:31'), 
    (3, 7, '2015-06-01 15:20:32'), 
    (4, 7, '2015-06-01 15:25:30'), 
    (5, 7, '2015-06-01 15:25:31') 
; 

查詢1

with c as (select *, 
      lag("timestamp") over(partition by stream_id order by id) as pre_time, 
      lag(id) over(partition by stream_id order by id) as pre_id 
      from Table1 
     ) 
select * from c where "timestamp" - pre_time > interval '2 sec' 

Results

| id | stream_id |    timestamp |    pre_time | pre_id | 
|----|-----------|------------------------|------------------------|--------| 
| 4 |   7 | June, 01 2015 15:25:30 | June, 01 2015 15:20:32 |  3 |