【问题标题】:find user sessions by grouping nearby timestamps通过对附近的时间戳进行分组来查找用户会话
【发布时间】:2014-11-12 17:15:05
【问题描述】:

我想根据“不活动时间”对 SQL 中的某些行进行 GROUP BY, 这意味着注意时间戳之间的巨大差距以识别用户 会议。

假设这个动作表在一个 sqlite 数据库中:

_actions_
| id | userID | timestamp | actionType |

现在我可以查看所有用户操作及其按小时、月、年等分组的类型。

SELECT 
    userID, strftime('%H', timestamp), group_concat(actionType)
FROM 
    actions 
GROUP BY userID, strftime('%H', timestamp);

然而,这并不完全是我想要的。考虑一下:

| 1 | 333 | 13.11.2014-20:59 | action6 |
| 2 | 333 | 13.11.2014-21:01 | action3 |
| 3 | 333 | 13.11.2014-21:47 | action5 |

我的示例合并到第 1 行和第 2+3 行,但是如果我们假设会话超时 30 分钟我们应该得到第 1+2 行和第 3 行。任何 sql-ideas 吗?

当然可以在 R、Pandas 等中加载数据库并检查每个用户,如果 current_timestamp - last_timestamp > 30 分钟,但这真的是要走的路吗?

【问题讨论】:

    标签: sqlite timestamp group-by date-difference


    【解决方案1】:

    要计算某行是会话中第一行的位置,请检查前 30 分钟内是否存在任何其他行:

    SELECT *,
           NOT EXISTS (SELECT 1
                       FROM actions AS prev
                       WHERE userid = actions.userid
                         AND timestamp < actions.timestamp
                         AND timestamp >= datetime(actions.timestamp, '-30 minutes')
                      ) AS first
    FROM actions;
    
    id          userid      timestamp         actiontype  first     
    ----------  ----------  ----------------  ----------  ----------
    1           333         2014-11-13 20:59  action6     1         
    2           333         2014-11-13 21:01  action3     0         
    3           333         2014-11-13 21:47  action5     1         
    

    但他并不能直接帮助分组;我们需要一些对组中所有行都是唯一的值。

    让我们获取组中第一行的 ID。 为了找到当前行的组的第一行,我们取 last 行,它是 some 组的第一行,并且是 not after em> 当前行:

    SELECT *,
           (SELECT id
            FROM actions AS first
            WHERE userid = actions.userid
              AND timestamp <= actions.timestamp
              AND NOT EXISTS (SELECT 1
                              FROM actions AS prev
                              WHERE userid = first.userid
                                AND timestamp < first.timestamp
                                AND timestamp >= datetime(first.timestamp, '-30 minutes')
                             )
            ORDER BY timestamp DESC
            LIMIT 1
           ) AS sessionid
    FROM actions;
    
    id          userid      timestamp         actiontype  sessionid 
    ----------  ----------  ----------------  ----------  ----------
    1           333         2014-11-13 20:59  action6     1         
    2           333         2014-11-13 21:01  action3     1         
    3           333         2014-11-13 21:47  action5     3         
    

    为了使这个查询高效,timestamp 列必须被索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-06
      • 2018-07-06
      • 2015-03-07
      • 1970-01-01
      • 2015-06-01
      • 2020-11-16
      • 1970-01-01
      相关资源
      最近更新 更多