在表中的日志条目之间花费的时间

时间:2014-03-05 05:45:19

标签: sql postgresql window-functions

我有一个跟踪网站中用户操作的表。简化版如下

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,获取下一个,找到差异。

我认为这需要一个递归查询,但无法理解它。有一件事 - 我不知道什么时候停下来。在一些“模块”之后,用户可以刚刚关闭浏览器,而无需注销。所以“关闭”有点棘手。

2 个答案:

答案 0 :(得分: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,其中没有其他操作 - 这看起来非常合适。

答案 1 :(得分: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&gt; = 9.0进行简化,但我无法使其工作。