【问题标题】:Window Function to increment over column on logical criteria窗口函数在逻辑标准上增加列
【发布时间】:2020-05-17 10:10:44
【问题描述】:

我正在寻找一种方法来根据以下标准添加与用户无关的“会话”列。

1) 每个用户定义自己的会话

2) +10 分钟的时间间隔为给定用户启动一个新会话。

因此对于输入:

| user_id | datetime_col     |
------------------------------
|1        |  01/01/2020 13:00|
|1        |  01/01/2020 13:01|
|1        |  01/01/2020 13:02|
|1        |  01/01/2020 13:20|
|1        |  01/01/2020 13:21|
|1        |  01/01/2020 13:22|
|1        |  01/01/2020 13:23|
|2        |  01/01/2020 13:00|
|2        |  01/01/2020 13:01|
|2        |  01/01/2020 13:02|
|2        |  01/01/2020 13:03|
|2        |  01/01/2020 13:04|
|3        |  01/01/2020 13:00|
|3        |  01/01/2020 13:01|
|3        |  01/01/2020 13:02|
|3        |  01/01/2020 13:03|
|3        |  01/01/2020 13:04|

我想要以下输出:

| user_id | datetime_col     | seesion_id|
------------------------------------------
|1        |  01/01/2020 13:00|     0     |
|1        |  01/01/2020 13:01|     0     |
|1        |  01/01/2020 13:02|     0     |
|1        |  01/01/2020 13:20|     1     |
|1        |  01/01/2020 13:21|     1     |
|1        |  01/01/2020 13:22|     1     |
|1        |  01/01/2020 13:23|     1     |
|2        |  01/01/2020 13:00|     2     |
|2        |  01/01/2020 13:01|     2     |
|2        |  01/01/2020 13:02|     2     |
|2        |  01/01/2020 13:03|     2     |
|2        |  01/01/2020 13:04|     2     |
|3        |  01/01/2020 13:00|     3     |
|3        |  01/01/2020 13:01|     3     |
|3        |  01/01/2020 13:02|     3     |
|3        |  01/01/2020 13:03|     3     |
|3        |  01/01/2020 13:04|     3     |

从概念上讲,我想计算每个用户每行之间的时间差,然后在每次 user_id 更改或时间滞后大于 10 分钟时递增。我可以做类似的事情

SELECT *,
DATE_PART('minutes', datetime_col - LAG(datetime_col, 1) OVER (PARTITION BY user_id ORDER BY datetime_col)) AS grp
FROM Table1

然后得到

| user_id | datetime_col     | grp       |
------------------------------------------
|1        |  01/01/2020 13:00|   (null)  |
|1        |  01/01/2020 13:01|     1     |
|1        |  01/01/2020 13:02|     1     |
|1        |  01/01/2020 13:20|    18     |
|1        |  01/01/2020 13:21|     1     |
|1        |  01/01/2020 13:22|     1     |
|1        |  01/01/2020 13:23|     1     |
|2        |  01/01/2020 13:00|   (null)  |
|2        |  01/01/2020 13:01|     1     |
|2        |  01/01/2020 13:02|     1     |
|2        |  01/01/2020 13:03|     1     |
|2        |  01/01/2020 13:04|     1     |
|3        |  01/01/2020 13:00|   (null)  |
|3        |  01/01/2020 13:01|     1     |
|3        |  01/01/2020 13:02|     1     |
|3        |  01/01/2020 13:03|     1     |
|3        |  01/01/2020 13:04|     1     |

但是从这里我被难住了,我该如何解决这个问题?

【问题讨论】:

    标签: sql postgresql window-functions


    【解决方案1】:

    您可以使用lag() 和累积总和计算每个用户的单独会话:

    select t.*,
           count(*) filter (where prev_dt < datetime_col - interval '10 minute') over (partition by user_id order by datetime_col) as session_id
    from (select t.*,
                 lag(datetime_col) over (partition by user_id order by datetime_col) as prev_dt
          from table1 t
         ) t;
    

    滞后获取上一个日期。然后,仅计算相隔超过 10 分钟的转换以获得session_id

    这对我来说最有意义。

    但您似乎想先按USER_ID 累积这些,然后按日期/时间(总体而言,按日期/时间对我来说更有意义)。这看起来很奇怪,但你可以使用dense_rank()

    with s as (
          select t.*,
                 count(*) filter (where prev_dt < datetime_col - interval '10 minute') over (partition by user_id order by datetime_col) as session_id
          from (select t.*,
                       lag(datetime_col) over (partition by user_id order by datetime_col) as prev_dt
                from table1 t
               ) t
         )
    select s.*,
            dense_rank() over (order by user_id, session_id) - 1 as new_session_id
    from  s
    order by user_id, datetime_col;
    

    Here 是一个 dbfiddle。

    【讨论】:

    • 我首先喜欢第一种方式,只是因为它更接近我想要做的事情。首先由user_id 累积的原因是两个用户在同时操作时定义了不同的会话。老实说,我不明白为什么会这样。
    猜你喜欢
    • 2016-04-06
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    相关资源
    最近更新 更多