在 sql 中对多行的连续会话进行分组
Grouping continuous sessions over multiple rows in sql
我正在尝试查看会话长度以查看用户连续登录的时间。问题是会话按 activity 分成几行。如果 Activity 结束与下一行 activity 开始相同,那么它们是同一会话的一部分,应该一起计算。
理想情况下它看起来像这样,我有 ACTIVITY_START 和 ACTIVITY_END 并且想创建会话:
ACTVITY_START | ACTIVITY_END | SESSION
----------------|-----------------|----------
2/16/2016 19:00 | 2/16/2016 20:51 | 1
2/16/2016 20:51 | 2/16/2016 20:52 | 1
2/16/2016 20:52 | 2/16/2016 20:54 | 1
2/16/2016 20:54 | 2/16/2016 21:25 | 1
2/16/2016 21:25 | 2/16/2016 21:26 | 1
2/16/2016 21:26 | 2/16/2016 22:13 | 1
2/16/2016 22:13 | 2/16/2016 22:14 | 1
2/16/2016 22:14 | 2/16/2016 22:41 | 1
2/18/2016 21:59 | 2/18/2016 23:07 | 2
2/18/2016 23:07 | 2/19/2016 0:00 | 2
2/19/2016 0:00 | 2/19/2016 1:56 | 2
2/19/2016 1:56 | 2/19/2016 1:58 | 2
2/19/2016 19:08 | 2/19/2016 20:53 | 3
2/19/2016 20:53 | 2/20/2016 0:00 | 3
2/20/2016 0:00 | 2/20/2016 0:05 | 3
2/20/2016 0:05 | 2/20/2016 2:00 | 3
2/20/2016 2:00 | 2/20/2016 2:12 | 3
2/20/2016 2:12 | 2/20/2016 2:28 | 3
2/20/2016 2:28 | 2/20/2016 2:32 | 3
2/20/2016 12:38 | 2/20/2016 14:16 | 4
2/20/2016 14:26 | 2/20/2016 14:27 | 5
最初我所做的是将 activity 结尾与同一行中的下一个 activity 开头对齐并做了:
SELECT DENSE_RANK() OVER (ORDER BY CASE WHEN A.ACTIVITY_END = B.ACTIVITY_START THEN 0 ELSE 1 END)
但是,当会话发生变化时,这会将所有会话放在一起进行排名。
我如何获得它以便每次新会话开始时 SESSION 递增?
即使您将问题标记为使用 MySQL 数据库,您使用 dense_rank()
window 函数执行 "successful" 查询的事实告诉我它是绝对不是 MySQL。 MySQL 目前不支持 window 函数。
不过,基于这样一个事实,无论您的数据库是什么,它都支持 windows 函数,我将继续并假设它包括对 lag
和 [=13= 的支持] window 函数。如果是这种情况,您可以使用 lag
函数来识别哪些行不是上一行的延续。然后您可以使用累积和根据 lag
函数生成的值生成会话 ID:
with cte as (
select a.*,
case when a.activity_start = lag(a.activity_end) over (order by a.activity_start)
then 0 else 1 end as grp_id
from activity a
)
select activity_start,
activity_end,
sum(grp_id) over (order by activity_start) as session_id
from cte
order by activity_start
我正在尝试查看会话长度以查看用户连续登录的时间。问题是会话按 activity 分成几行。如果 Activity 结束与下一行 activity 开始相同,那么它们是同一会话的一部分,应该一起计算。
理想情况下它看起来像这样,我有 ACTIVITY_START 和 ACTIVITY_END 并且想创建会话:
ACTVITY_START | ACTIVITY_END | SESSION
----------------|-----------------|----------
2/16/2016 19:00 | 2/16/2016 20:51 | 1
2/16/2016 20:51 | 2/16/2016 20:52 | 1
2/16/2016 20:52 | 2/16/2016 20:54 | 1
2/16/2016 20:54 | 2/16/2016 21:25 | 1
2/16/2016 21:25 | 2/16/2016 21:26 | 1
2/16/2016 21:26 | 2/16/2016 22:13 | 1
2/16/2016 22:13 | 2/16/2016 22:14 | 1
2/16/2016 22:14 | 2/16/2016 22:41 | 1
2/18/2016 21:59 | 2/18/2016 23:07 | 2
2/18/2016 23:07 | 2/19/2016 0:00 | 2
2/19/2016 0:00 | 2/19/2016 1:56 | 2
2/19/2016 1:56 | 2/19/2016 1:58 | 2
2/19/2016 19:08 | 2/19/2016 20:53 | 3
2/19/2016 20:53 | 2/20/2016 0:00 | 3
2/20/2016 0:00 | 2/20/2016 0:05 | 3
2/20/2016 0:05 | 2/20/2016 2:00 | 3
2/20/2016 2:00 | 2/20/2016 2:12 | 3
2/20/2016 2:12 | 2/20/2016 2:28 | 3
2/20/2016 2:28 | 2/20/2016 2:32 | 3
2/20/2016 12:38 | 2/20/2016 14:16 | 4
2/20/2016 14:26 | 2/20/2016 14:27 | 5
最初我所做的是将 activity 结尾与同一行中的下一个 activity 开头对齐并做了:
SELECT DENSE_RANK() OVER (ORDER BY CASE WHEN A.ACTIVITY_END = B.ACTIVITY_START THEN 0 ELSE 1 END)
但是,当会话发生变化时,这会将所有会话放在一起进行排名。
我如何获得它以便每次新会话开始时 SESSION 递增?
即使您将问题标记为使用 MySQL 数据库,您使用 dense_rank()
window 函数执行 "successful" 查询的事实告诉我它是绝对不是 MySQL。 MySQL 目前不支持 window 函数。
不过,基于这样一个事实,无论您的数据库是什么,它都支持 windows 函数,我将继续并假设它包括对 lag
和 [=13= 的支持] window 函数。如果是这种情况,您可以使用 lag
函数来识别哪些行不是上一行的延续。然后您可以使用累积和根据 lag
函数生成的值生成会话 ID:
with cte as (
select a.*,
case when a.activity_start = lag(a.activity_end) over (order by a.activity_start)
then 0 else 1 end as grp_id
from activity a
)
select activity_start,
activity_end,
sum(grp_id) over (order by activity_start) as session_id
from cte
order by activity_start