1

我想根据“不活动时间”对 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 想法?

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

4

1 回答 1

0

要计算某行是会话中第一行的位置,请检查前 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。为了找到当前行的组的第一行,我们取最后一行,即某个组的第一行并且不在当前行之后:

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必须为该列编制索引。

于 2014-11-12T21:20:12.340 回答