Hive实战—时间滑动窗口计算
关注公众号:
大数据技术派,回复:资料,领取1024G资料。
时间滑动计算
今天遇到一个需求大致是这样的,我们有一个业务涉及到用户打卡,用户可以一天多次打卡,我们希望计算出7天内打卡8次以上,且打卡时间分布在4天以上的时间,当然这只是个例子,我们具体解释一下这个需求
- 用户一天可以打卡多次,所以要求打卡必须分布在4天以上;
- 7天不是一个自然周,而是某一天和接下来的6天,也就是说时间是是滑动的,窗口大小是7步长是1,说白了就是窗口计算;
其实说到这里你就想到了窗口函数,虽然这是一个窗口;但是hive却没有相应的窗口函数可以计算,接下来我们看一下怎么实现这个逻辑
外部调用实现时间循环
我们可以先写这样的一个SQL,就计算每个人在特定时间内是否满足我们的条件,我们先计算出每个人每天的打卡次数,例如这里我们的时间限制是'20210701' 到'20210707'
select
b.union_id,to_date(ds,'yyyymmdd') as dt,count(1) as cnt
from
ods_la_daily_record_di b
where
-- 驱动表的时间限制
b.ds>='${bizdate}'
and b.ds<=${bizdate2}'
group by
b.union_id,ds
然后我们再判断这个时间端内,用户的打卡情况是否满足我们的条件
select
union_id,count(1) as 打卡天数, sum(cnt) as 打卡次数
from
(
select
b.union_id,ds,count(1) as cnt
from
ods_la_daily_record_di b
where
-- 驱动表的时间限制
b.ds>='${bizdate}'
and b.ds<='${bizdate2}'
group by
b.union_id,ds
)
group by
union_id
having
-- 时间分布在4天以上
count(1)>=4
-- 打卡次数在8次以上
and sum(cnt)>=8
;

这样我们就算出来我们需要的数据,接下来我们只需要用其他语言调用这个SQL ,传入不同的时间参数就可以了,利用编程语言实现时间的滑动,例如第一次传入'20210701-20210707' 第二次传入'20210702-20210708' 以此传入即可。
虽然可以实现,但是不好,因为我们还需要其他语言的调用,其实我们知道在SQL里面的关联其实就是通过循环实现的,那我们即然能通过循环实现这个需求,我们能不能通过关联实现这个需求呢
自关联实现滑动时间窗口
其实我们只要让用户某一天的数据和他接下来的6天的数据关联,然后按照这一天的数据进行汇总然后判断时候满足我们的条件即可,如果满足了条件,那么用户这一天的数据就是满足我们的需求的,也就是说这个用户是满足我们的需求的。
with tmp as(
-- 每个人每天打卡的次数
select
b.union_id,to_date(ds,'yyyymmdd') as dt,count(1) as cnt
from
ods_la_daily_record_di b
where
-- 驱动表的时间限制
b.ds>='${bizdate}'
group by
b.union_id,ds
)
select
union_id
from (
-- 满足条件的(用户-天)
select
a.union_id,a.dt,sum(b.cnt) as 打卡次数,count(1) as 打卡天数
from
tmp a
inner join
tmp b
on
a.union_id=b.union_id
and DATEDIFF(b.dt,a.dt)>=0
and DATEDIFF(b.dt,a.dt)<=6
group by
a.union_id,a.dt
having
-- 次数限制
sum(b.cnt)>=8
-- 天数限制
and count(1)>=4
)group by
-- 对用户去重
union_id
;
这里有一个问题需要注意一下,那就是我们满足条件sum(b.cnt)>=8 and count(1)>=4 的是用户某一天的数据,也就是说我们的维度是union_id-天,所以我们需要对这个数据按照用户为度进行去重。
扩展基于自然周的的滚动时间窗口计算
我们这里思考一个问题,那就是我们知道很多时候我们的计算其实是围绕着自然周的,虽然我们上面的计算不是自然周,那假设我们如果要求我们的计算是自然周呢,那这个时候我们应该怎么计算呢,其实我们数仓里有一种很表叫做时间维表,我们利用时间维表可以很方便的计算时间相关的东西,如果你没有的话建议去网上找一份,或者自己生成一份,因为使用起来很方便。

因为这个表的字段很多,这里我们截取了一部分放到这里了,下面我们看一下怎么使用时间维表进行计算。
select
UNION_ID,time_weeknum,count(1) as 打卡天数, sum(cnt) as 打卡次数
from(
select
b.union_id,ds,count(1) as cnt
from
ods_la_daily_record_di b
where
-- 驱动表的时间限制
b.ds>='${bizdate}'
and b.ds<='${bizdate2}'
group by
b.union_id,ds
) a
left join
dim_date_time b
on
a.ds=b.time_date
group by
-- 周的标识
UNION_ID,time_weeknum
HAVING
-- 时间分布在4天以上
count(1)>=4
-- 打卡次数在8次以上
and sum(cnt)>=8
;
这里我们就基于每个自然周算出了满足条件的人,当然我们还是要针对用户去重
总结
我们看到自关联其实可以达到滑动的效果,当然不仅仅体现在时间上,就像窗口除了时间窗口还是有基于个数的窗口,我们要在遇到类似问题的时候就可以选择这样的解决方案。
时间维表很重要,可以简化我们的计算,如果没有的话,需要创建一个。
交流群
加我微信:ddxygq,回复加群,我拉你进技术交流群。
猜你喜欢
数仓建模—指标体系
数仓建模—宽表的设计
Spark SQL知识点与实战
Hive计算最大连续登陆天数
Flink计算pv和uv的通用方法
Hive实战—时间滑动窗口计算的更多相关文章
- uva12174 滑动窗口+预处理
注意理解题意,不是排列种类,而是下一个排序出现的时间滑动窗口,具体见代码,写了很多注释(紫书的思路1理解有点麻烦...)注:可以画一个轴来方便理解 #include<iostream> # ...
- Spark-Streaming之window滑动窗口应用
Spark-Streaming之window滑动窗口应用,Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据,会被 ...
- 57、Spark Streaming: window滑动窗口以及热点搜索词滑动统计案例
一.window滑动窗口 1.概述 Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据, 会被聚合起来执行计算操作 ...
- Flink 滑动窗口使用触发器会触发多个窗口的计算
之前有小伙伴在群里说:滑动窗口使用触发器让每条数据都触发一次计算 但是他并没有得到预期的结果:每条数据都触发一次计算,输出一条结果,而是每天数据都输出了很多条结果 为什么会这样呢? 写了个小案例,来解 ...
- 【图解】你还在为 TCP 重传、滑动窗口、流量控制、拥塞控制发愁吗?看完图解就不愁了
每日一句英语学习,每天进步一点点: 前言 前一篇「硬不硬你说了算!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题」得到了很多读者的认可,在此特别感谢你们的认可,大家都暖暖的. 来了,今 ...
- tcp协议头窗口,滑动窗口,流控制,拥塞控制关系
参考文章 TCP 的那些事儿(下) http://coolshell.cn/articles/11609.html tcp/ip详解--拥塞控制 & 慢启动 快恢复 拥塞避免 http://b ...
- TCP 滑动窗口和 拥塞窗口
转http://coolshell.cn/articles/11609.html 滑动窗口 -- 表征发送端和接收端的接收能力 拥塞窗口-- 表征中间设备的传输能力 TCP滑动窗口 需要说明一下,如果 ...
- storm 1.0版本滑动窗口的实现及原理
滑动窗口在监控和统计应用的场景比较广泛,比如每隔一段时间(10s)统计最近30s的请求量或者异常次数,根据请求或者异常次数采取相应措施.在storm1.0版本之前,没有提供关于滑动窗口的实现,需要开发 ...
- tcp滑动窗口详解(2)
http://blog.csdn.net/yujun00/article/details/636495 ARQ与滑动窗口概念 滑动窗口协议,是TCP使用的一种流量控制方法.该协议允许发送方在停止并等 ...
随机推荐
- 图片处理看这篇就完了「GitHub 热点速览 v.21.48」
作者:HelloGitHub-小鱼干 图像处理一直是个实用且热门的研究领域,而本周的 GitHub 项目则多个图像项目上榜.先是勉强和图像处理搭边的渲染引擎 Filament,它能渲染出效果极佳的 3 ...
- 一次奇怪的的bug排查过程
公司对底层基础库进行了重构,线上稳定跑了几天,在查看订单系统的log时,有几条error信息非常的奇怪, orderID:80320180 statemachine error: no event [ ...
- .NET Core基础篇之:依赖注入DependencyInjection
依赖注入已经不是什么新鲜话题了,在.NET Framework时期就已经出现了各种依赖注入框架,比如:autofac.unity等.只是在.net core微软将它搬上了台面,不用再依赖第三方组件(那 ...
- 数据库连接池配置 testOnBorrow
背景 前段时间做系统压测,发现DB的CPU使用率飙升很严重,排查后发现是一个配置testOnBorrow由false修改为true导致.怎么对性能影响这么大?需要好好了解一下. testOnBorro ...
- R语言中的read.table()
参考资料:http://www.cnblogs.com/xianghang123/archive/2012/06/06/2538274.html read.table(file, header = F ...
- java中接口可以继承接口
今天阅读别人的代码才发现,接口是可以继承接口的 一个类只能extends一个父类,但可以implements多个接口. 一个接口则可以同时extends多个接口,却不能implements任何接口. ...
- LInkedList总结及部分底层源码分析
LInkedList总结及部分底层源码分析 1. LinkedList的实现与继承关系 继承:AbstractSequentialList 抽象类 实现:List 接口 实现:Deque 接口 实现: ...
- C/C++ Qt 数据库与TreeView组件绑定
在上一篇博文<C/C++ Qt 数据库QSql增删改查组件应用>介绍了Qt中如何使用SQL操作函数,并实现了对数据库的增删改查等基本功能,从本篇开始将实现数据库与View组件的绑定,通过数 ...
- github小白的记录随笔
此文章是基础本地安装好了git环境的新手小白. 进入您要上传项目的根路径,右键选择Git Bash Here. 输入命令: git init //初始化git仓库环境 git remote add o ...
- 最长公共子序列问题(LCS) 洛谷 P1439
题目:P1439 [模板]最长公共子序列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 关于LCS问题,可以通过离散化转换为LIS问题,于是就可以使用STL二分的方法O(nlogn ...