hive sql练习2:统计用户在每个时间段的在线时长

习题描述

表里有用户进入和离开的时间,统计用户在每个时间段的在线时长
题目场景不固定,根据大致题意,做出下面场景假设(下面假设场景中的表结构均为自己假设,如有问题请大佬指出)。

假设1

场景: 同一会话下记录用户的进入和离开时间,那就是每一次进入就是新的会话,然后统计按小时,或者按每10分钟段的在线时长。
表结构:

表结构
user_id      --用户id
session_id   --会话id
in_time      --进入时间
out_time     --离开时间

假设2

场景:用户在同一会话下记录进入和离开 两个事件,也就是记录两条数据,多的就是事件(进入,离开标志),然后计算时间段时长。

表结构
user_id        --用户id
session_id     --会话id
event_time     --事件时间
event_flag     --事件标志

实现

假设1

--取某一天的所有小时间隔时间
with tmp as(
select 
from_unixtime(unix_timestamp('2023-02-17 00:00:00') + pos * 60 *60 , 'yyyy-MM-dd HH:mm:ss') as time
from (
select posexplode(split(space(23), ' ')) as (pos, val)
) t
)
--临时造的场景 1 所需测试数据
,tmp1 as(
select '1' as user_id, '1' as session_id, '2023-02-17 01:10:00' as in_time, '2023-02-17 04:10:00' as out_time union all 
select '1' as user_id, '2' as session_id, '2023-02-17 04:11:00' as in_time, '2023-02-17 04:16:10' as out_time union all 
select '2' as user_id, '1' as session_id, '2023-02-17 04:00:00' as in_time, '2023-02-17 04:16:00' as out_time union all 
select '2' as user_id, '2' as session_id, '2023-02-17 05:00:00' as in_time, '2023-02-17 07:00:00' as out_time 
)
--将每条数据(每个用户下的每个会话id)与当天所有时间段时间取笛卡尔积,
--行转列,将每次会话的进入和离开时间的两列,合并到一列里面,
--并对所在会话时间段的时间打标记
,tmp2 as(
select user_id, session_id, time as times, if(in_time < time and time < out_time, 1, null) as flag from tmp, tmp1 union all 
select user_id, session_id, in_time as times, 1 as flag from tmp1 union all 
select user_id, session_id, out_time as times, null as flag from tmp1
)
--对所有数据按用户的每次会话分组,按时间升序排序,窗口内取每条数据下条数据的时间,即取下条相邻时间
,tmp3 as(
select 
user_id, session_id, times, flag,
lead(times, 1) over(partition by user_id, session_id order by times) as times2
from tmp2
group by user_id, session_id, times, flag
)
--求每个用户每次会话所在每个时间段的时间
--取所有标记内的数据,并取相邻两个时间段的差值(单位分钟)
,tmp4 as(
select 
user_id, session_id, times, times2, flag,
(unix_timestamp(times2) - unix_timestamp(times)) / 60 as m_time
from tmp3
where flag = 1
)
--求每个用户所在每个时间段的时间总和
select 
user_id, date_format(times,'yyyy-MM-dd HH:00:00'),
sum(m_time) as m_time
from tmp4
group by user_id, date_format(times,'yyyy-MM-dd HH:00:00')
;

假设2

感觉跟场景 1 类似,只不过场景 1 是一条数据,场景 2 是两条数据,但是我们场景 1 的做法是将一条数据拆为了两条数据,这么看就与场景 2 一致,所以场景 2 应该比场景 1 少一步拆解数据的动作,其余感觉均与场景 1 写法一致。


以上均为自己根据题意假设所做,如有错误或者更好的方法,请大佬指正。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值