2014-03-05 12 views
0

我有一個表跟蹤用戶在網站中的操作。簡化版本如下在一個表中的日誌條目之間花費的時間

user_id | action_time    | module_name 
--------+-------------------------+------------ 
1  | 2014-03-02 11:13:08.775 | home 
1  | 2014-03-02 11:13:08.345 | user 
1  | 2014-03-02 11:13:08.428 | discussions 

用戶在每個屏幕上花了多少時間?所以對於一個用戶來說至少需要action_time,得到下一個,找到差異。

我認爲這需要一個遞歸查詢,但無法讓我的頭在附近。有一件事 - 我不知道什麼時候停止。在一些「模塊」之後,用戶可以關閉瀏覽器,而不必註銷。所以「關閉」有點棘手。

回答

3

這可能是與window function lead()

SELECT * 
    , lead(action_time) OVER (PARTITION BY user_id ORDER BY action_time) 
     - action_time AS time_spent 
FROM tbl; 

這一切非常簡單。

time_spentNULL對於用戶的最後一個動作,其中沒有其他動作如下 - 這似乎是非常合適的。

0

這個如何使用窗口函數和大量嵌套子查詢來創建'範圍聚集'的例子。我只是適應它由USER_ID分區和分組,它似乎你想要做什麼:

SELECT user_id, min(login_time) as login_time, max(logout_time) as logout_time 
FROM (
    SELECT user_id, login_time, logout_time, 
     max(new_start) OVER (PARTITION BY user_id ORDER BY login_time, logout_time) AS left_edge 
    FROM (
     SELECT user_id, login_time, logout_time, 
      CASE 
       WHEN login_time <= max(lag_logout_time) OVER (
        PARTITION BY user_id ORDER BY login_time, logout_time 
       ) THEN NULL 
       ELSE login_time 
      END AS new_start 
     FROM (
      SELECT 
       user_id, 
       login_time, 
       logout_time, 
       lag(logout_time) OVER (PARTITION BY user_id ORDER BY login_time, logout_time) AS lag_logout_time 
      FROM app_log 
     ) AS s1 
    ) AS s2 
) AS s3 
GROUP BY user_id, left_edge 
ORDER BY user_id, min(login_time) 
Results in: 



user_id |  login_time  |  logout_time 
---------+---------------------+--------------------- 
     1 | 2014-01-01 08:00:00 | 2014-01-01 10:49:00 
     1 | 2014-01-01 10:55:00 | 2014-01-01 11:00:00 
     2 | 2014-01-01 09:00:00 | 2014-01-01 11:49:00 
     2 | 2014-01-01 11:55:00 | 2014-01-01 12:00:00 
(4 rows) 

它的工作原理是首先檢測每一個新系列的開始(由USER_ID分區),然後延伸並由分組檢測範圍。我發現我必須非常仔細地閱讀這篇文章才能理解它!

該文章建議通過刪除最內層的子查詢和更改窗口範圍,可以使用Postgresql> = 9.0簡化它,但我無法使其工作。