题目
计算最大同时在线人数,表connection_detail记录用户每一次上线和下线时间:
user_id | login_time(上线时间)) | logout_time(下线时间) | dt |
---|---|---|---|
213142 | 2019-01-01 12:21:22 | 2019-01-01 13:45:21 | 20190101 |
412321 | 2019-01-01 13:35:11 | 2019-01-01 16:01:49 | 20190101 |
… | … | … | … |
解法
大致思路 窗口函数 sum() over()
我们先抛开sql,来考虑实时计算中我们怎么处理该问题。是不是我们会实时记录着一个变量online_cnt,当一个用户登录时加1,用户下线时减1?
再假如我让你用python离线处理这个问题你会怎么做。应该先把登录时间和登出时间这两列打散成行,然后进行排序,最后一行行读入,当读到一个登录时间时online_cnt加1,读到登出时间时online_cnt减1。
回到sql,我们来尝试用SQL实现上述逻辑。我们给登录时间加一个数值标记1,登出时间加标记-1。然后对排序后的数据求和该字段,最终得到我们的结果。
select
max(max_index)
from
(
select
sum(index) over(order by `timestamp`) as max_index --排序后第一行到本行的和
from
(
select
order_id,
unix_timestamp(login_time) as `timestamp`,
1 as index
from
connection_detail
where
dt = '20190101'
and is_td_finish = 1
union all
select
order_id,
unix_timestamp(logout_time) as `timestamp`,
-1 as index
from
connection_detail
where
dt = '20190101'
)a --将登录时间和登出时间多列成多行
)b
对于sum() over()的用法,不熟悉的同学可以看我的博客sum(…) over(…) 连续求和分析函数。
该代码对于千万量级的数据sparksql计算了65秒,属于一个可以接受的范围。