我想在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分钟,但这真的是要走的路吗?
答案 0 :(得分: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。 要查找当前行组的第一行,我们将 last 行作为某些组的第一行,而不在>之后当前行:
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
列编入索引。