Hive SQL必刷练习题:连续问题 间断连续

news/2025/1/13 12:24:03/

问题描述:

1) 连续问题:找出连续三天(或者连续几天的啥啥啥)。

2) 间断连续:统计各用户连续登录最长天数,间断一天也算连续,比如1、3、4、6也算登陆了6天

问题分析:

这两类问题,都是涉及到连续,只不过连续类问题只要判断出来相邻的时间是和当前行的时间挨着即可,而间断连续,是还可能在期间有中断现象,并且即使中断了,也要算在连续的时间内,比如1、3、4、6号登录,但是算是连续登陆了6天。所以只要中断不超过两天,也能判断出来是连续的,并且在计算连续天数的时候还要算上这个时间。

解决思路:

1)针对连续问题:

可以通过对每一个用户id进行开窗,然后排序里面的时间,加上row_number(),这样对每一个日期都会有一个排序,之后将日期减去排序序号,只要这个值是一样的,就说明这几天是连续的。之后只要根据用户id,以及这个减去过排序序号的差值diff进行一起group by分组,然后通过having count(*) >= 3,这个筛选条件过滤出的结果就是最终连续登录了三天的用户

2)针对间断连续问题:

​ 也是对每一个用户id进行开窗,只不过这次是针对当前行,用lag()取上一行数据。【必须要看上一行,而不是看下一行,因为如果当前行开始变化,当前行需要记录,如果看下一行,那看的是下一行有没有变化,是不是不连续了之类的,下一行的情况无法记录】。之后用当天日期对这个用开窗函数得到的上一天日期进行相减,如果大于2,就说明相邻两天的日期是超过了2天,按照定义不算是“连续”,所以增加个标记,记录为1,这样每一行都会有一个标记,如果是连续的,那这一行后面就标记的0

​ 接下来就是关键的步骤,根据**用户id进行开窗求sum聚合group by,然后从最开始的一行,到当前行,进行求sum。**这样的话,原本是1、0、0、1、0、1、0,比如是这样的标记序列,每到一个1就说明从这天开始,就不是间断一天连续了,然后从最开始一行到当前行求sum的结果就是,1、1、1、2、2、3、3。这就很好的划分出来三段“间断连续时间”。

​ 然后根据用户id,以及这个标记进行分组聚合group by,求出来这个期间日期的max,以及日期的min,相减,别忘了再加1【日期计算时候需要注意的】,就是这个间断连续的天数了。

总结:

​ 所以总的来说,要么就是用开窗函数对日期进行排序,然后当前日期减去排序序号,去看日期一样的就是连续操作的记录

​ 当然,如果想用统计间断连续的方法去看连续n天的问题,也可以,就是取一个lag(),或者取一个lead(),进行开窗,不用加标记,直接一个where过滤diff=2,这就是统计连续3天的用户,不过同一个用户可能会有多个这个符合条件的,最后需要去重count(distinct(user_id)) 。如果是为了找到连续3天登录过的用户

​ 要么就是利用开窗函数取得上一行lag()日期,两个日期相减,去判断是否符合条件,接下来加一个标记,不符合的设为1,用作记录改变的时间点,其余标0。然后开窗函数对标记进行求和,是从第一条到当前条,这样就可以看出来一个用户id,划分了几个连续时间段,然后再根据需求去具体的求。

然后上代码:

1) 连续:

sql">seleet id
from (selectid,dt,date_sub(dt, row _number( over(partition by id order by dt) rk) as difffrom (select id, dt, sum(lowcarbon) lowcarbonfrom testlgroup by id, dthaving lowcarbon >100) t1
) t2
group by id, diff
having count(*) >= 3

2) 间断连续

selectuser_id,max(recent_days) max_recent_days  --求出每个用户最大的连续天数
from
(selectuser_id,user_flag,datediff(max(login_date),min(login_date)) + 1 recent_days --按照分组求每个用户每次连续的天数(记得加1)from(selectuser_id,login_date,lag1_date,concat(user_id,'_',flag) user_flag --拼接用户和标签分组from(selectuser_id,login_date,lag1_date,sum(if(datediff(login_date,lag1_date)>2,1,0)) over(partition by user_id order by login_date) flag  --获取大于2的标签from(selectuser_id,login_date,lag(login_date,1,'1970-01-01') over(partition by user_id order by login_date) lag1_date  --获取上一次登录日期from(selectuser_id,date_format(login_datetime,'yyyy-MM-dd') login_datefrom login_eventsgroup by user_id,date_format(login_datetime,'yyyy-MM-dd')  --按照用户和日期去重)t1)t2)t3)t4group by user_id,user_flag
)t5
group by user_id;)t2)t3)t4group by user_id,user_flag
)t5
group by user_id;

http://www.ppmy.cn/news/1562805.html

相关文章

(长期更新)《零基础入门 ArcGIS(ArcScene) 》实验七----城市三维建模与分析(超超超详细!!!)

城市三维建模与分析 三维城市模型已经成为一种非常普遍的地理空间数据资源,成为城市的必需品,对城市能化管理至关重要。语义信息丰富的三维城市模型可以有效实现不同领域数据与IS相信息的高层次集成及互操作,从而在城市规划、环境模拟、应急响应和辅助决策等众多领域公挥作用、…

使用Cilium/eBPF实现大规模云原生网络和安全

大家读完觉得有帮助记得关注和点赞!!! 目录 抽象 1 Trip.com 云基础设施 1.1 分层架构 1.2 更多细节 2 纤毛在 Trip.com 2.1 推出时间表 2.2 自定义 2.3 优化和调整 2.3.1 解耦安装 2.3.2 避免重试/重启风暴 2.3.3 稳定性优先 2…

CentOS 7.9 通过 yum 安装 Docker

文章目录 前言一、删除已安装的 Docker二、网络设置三、设置 yum 源,并安装依赖四、设置 Docker 仓库五、安装及使用 Docker六、镜像仓库总结 前言 CentOS 7.9 过了维护期,Docker 官方文档没有了相关的安装文档。记录一下,备用! …

30天开发操作系统 第 12 天 -- 定时器 v1.0

前言 定时器(Timer)对于操作系统非常重要。它在原理上却很简单,只是每隔一段时间(比如0.01秒)就发送一个中断信号给CPU。幸亏有了定时器,CPU才不用辛苦地去计量时间。……如果没有定时器会怎么样呢?让我们想象一下吧。 假如CPU看不到定时器而仍想计量时…

基于物联网技术的电动车防盗系统设计(论文+源码)

1总体设计 本课题为基于物联网技术的电动车防盗系统,在此将整个系统架构设计如图2.1所示,其采用STM32F103单片机为控制器,通过NEO-6M实现GPS定位功能,通过红外传感器检测电瓶是否离开位,通过Air202 NBIOT模块将当前的…

计算机网络(三)——局域网和广域网

一、局域网 特点:覆盖较小的地理范围;具有较低的时延和误码率;使用双绞线、同轴电缆、光纤传输,传输效率高;局域网内各节点之间采用以帧为单位的数据传输;支持单播、广播和多播(单播指点对点通信…

探索 Docker Desktop:简化开发与部署的利器

亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、Java 与 Python 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在未来…

stacking中如何把基础学习器设置为ann神经网络

在Stacking集成学习方法中,将人工神经网络(ANN)作为基础学习器是可行的,以下是一般的步骤: 一、数据准备 数据划分 首先,将原始数据集划分为训练集和测试集。例如,对于一个包含 n n n 个样本的数据集 D =