我在PostgreSQL中有带时间戳列created_at
和整数列的表user_id
。
id | created_at | user_id
1 | 2019-10-14 09:26:53.813 | 1
2 | 2019-10-14 09:26:54.813 | 1
3 | 2019-10-14 09:46:53.813 | 1
4 | 2019-10-14 09:46:54.813 | 2
5 | 2019-10-14 09:46:55.813 | 1
6 | 2019-10-14 09:46:56.813 | 1
7 | 2019-10-14 09:46:57.813 | 2
每行代表用户的某些操作。我需要计算平均用户会话长度。会话定义为时间差小于10分钟的一组动作。当两个用户操作之间相差10分钟或更长时间时,新会话开始。
我在想:
user_id
。但是我不能用SQL编写它。
您能给我一些建议/示例如何在SQL中完成吗?
SELECT
user_id,
AVG(diff)
FROM (
SELECT DISTINCT
user_id,
group_id,
first_value(created_at) OVER (PARTITION BY user_id, group_id ORDER BY created_at DESC)
- first_value(created_at) OVER (PARTITION BY user_id, group_id ORDER BY created_at) as diff
FROM (
SELECT
id, created_at, user_id,
SUM(group_id) OVER (PARTITION BY user_id ORDER BY created_at) AS group_id
FROM (
SELECT
*,
(created_at
- lag(created_at, 1, created_at) OVER (PARTITION BY user_id ORDER BY created_at)
> interval '10 minutes')::int AS group_id
FROM
mytable
)s
)s
)s
GROUP BY user_id
(created_at - lag(created_at, 1, created_at) OVER (PARTITION BY user_id ORDER BY created_at) > interval '10 minutes')::int AS group_id
:lag()
窗口函数created_at
从有序user_id
分区(组)中取自上一个记录的值(第二个参数:步长,第三个参数:如果没有上一个记录==当前值,则为默认值)。然后created_at
计算当前值与前一个值之间的差。如果此值> 10分钟,则结果为true
; false
除此以外。该布尔值可以转换为一个int
值,结果为0
或1
SUM()
在0
/1
值,这导致group_id
S表示每每一个新的会话user_id
user_id
会话的第一个created_at时间戳group_id
可以通过first_value()
window函数获取,最后一个byfirst_value()
和DESC
order可以获取。不同之处在于您每次会话的时长。使用该DISTINCT
子句是因为将差值放在每个记录上。但是我们只需要一次。AVG()
为用户分组和区别。本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句