强哥说他发现了财富密码,最近搞了一套股票算法,其中有一点涉及到股票连续涨停天数的计算方法,我们都知道股票周末是不开市的,这里有个断层,需要一点技巧。我问是不是时间序列,他说我瞎扯,我也知道自己是瞎扯。问他方法,他竟然不告诉我,这么多年的兄弟情谊算个屁。真当我没他聪明吗,哼!

靠人不如靠自己,我决定连夜研究一下在Hive里面计算最大连续天数的计算方法。

一、背景

在网站平台类业务需求中用户的「最大登陆天数」,需求比较普遍。

原始数据:

u0001 2019-10-10
u0001 2019-10-11
u0001 2019-10-12
u0001 2019-10-14
u0001 2019-10-15
u0001 2019-10-17
u0001 2019-10-18
u0001 2019-10-19
u0001 2019-10-20
u0002 2019-10-20

说明:数据是简化版,两列分别是user_id,log_in_date。现实情况需要从采集数据经过去重,转换得到以上形式数据。

我们先建表并且将数据导入Hive

create table test.user_log_1 (user_id string, log_in_date string) row format delimited fields terminated by ' ';

load data local inpath '/var/lib/hadoop-hdfs/data/user_log.txt' into table test.user_log_1 ;

查看一下数据:

hive> select * from test.user_log_1 ;
OK
u0001 2019-10-10
u0001 2019-10-11
u0001 2019-10-12
u0001 2019-10-14
u0001 2019-10-15
u0001 2019-10-17
u0001 2019-10-18
u0001 2019-10-19
u0001 2019-10-20
u0002 2019-10-20
Time taken: 0.076 seconds, Fetched: 10 row(s)

二、算法

核心是按访问时间排序,登陆时间列减去排序后的序列号,得到一个日期值,按这个值分组计数即可。

1. 第一步:排序

按照user_id分组,并且按照日期log_in_date排序:

select user_id, log_in_date, row_number() over(partition by user_id order by log_in_date) as rank from test.user_log_1;

结果:

u0001	2019-10-10	1
u0001 2019-10-11 2
u0001 2019-10-12 3
u0001 2019-10-14 4
u0001 2019-10-15 5
u0001 2019-10-17 6
u0001 2019-10-18 7
u0001 2019-10-19 8
u0001 2019-10-20 9 u0002 2019-10-20 1

这里可以看出,u0001这个用户最大连续登录天数是4天,使用后面计算方法计算后可以验证。

2. 第二步:第二列与第三列做日期差值

可以看出规律,日期小的,行号也小;如果将日期跟行号做差值,连续登录的差值应该是一样的。

select user_id, date_sub(log_in_date, rank) dts from (select user_id, log_in_date, row_number() over(partition by user_id order by log_in_date) as rank from test.user_log_1)m;

结果:

u0001	2019-10-09
u0001 2019-10-09
u0001 2019-10-09
u0001 2019-10-10
u0001 2019-10-10
u0001 2019-10-11
u0001 2019-10-11
u0001 2019-10-11
u0001 2019-10-11
u0002 2019-10-19

显然可以看出,最大连续连续登录是4次。

3. 第三步:按第二列分组求和

select user_id, dts, count(1) num from (select user_id, date_sub(log_in_date, rank) dts from (select user_id, log_in_date, row_number() over(partition by user_id order by log_in_date) as rank from test.user_log_1)m)m2 group by user_id, dts;

结果:

u0001	2019-10-09	3
u0001 2019-10-10 2
u0001 2019-10-11 4
u0002 2019-10-19 1

4. 第四步:求最大次数

已经算出了,每个用户连续登录天数序列,接下取每个用户最大登录天数最大值即可:

select user_id, max(num) from (select user_id, dts, count(1) num from (select user_id, date_sub(log_in_date, rank) dts from (select user_id, log_in_date, row_number() over(partition by user_id order by log_in_date) as rank from test.user_log_1)m)m2 group by user_id, dts)m3 group by user_id;

结果跟我们的预期是一致的,用户u0001最大登录天数是4。

u0001	4
u0002 1

三、扩展(股票最大涨停天数)

我们知道股票市场,比如咱们的A股,周末是不开盘的,那么一只股票如果上周五涨停,本周一接着涨停,这算是连续2天涨停,使用上面这种方法是不行的,使用lead函数试试:

select user_id, log_in_date, lead(log_in_date) over(partition by user_id order by log_in_date) end_date from test.user_log_1;

结果

u0001	2019-10-10	2019-10-11
u0001 2019-10-11 2019-10-12
u0001 2019-10-12 2019-10-14
u0001 2019-10-14 2019-10-15
u0001 2019-10-15 2019-10-17
u0001 2019-10-17 2019-10-18
u0001 2019-10-18 2019-10-19
u0001 2019-10-19 2019-10-20
u0001 2019-10-20 NULL
u0002 2019-10-20 NULL

哈哈,是不是有思路了。

思路:上面结果一共有3列,第一列是uid,通过lead函数,后面两列都是日期,那么两列日期都取值周一周五之间,也就是说数据里面只有工作日日期,没有周末的数据,可以提前过滤使得数据满足,既然要连续,那么:

  1. 如果第三列的日期,减去第二列的日期,差值等于1,显然是连续的;
  2. 如果第三列的日期,减去第二列的日期,差值等于3,但是第三列日期是星期一,那么也算是连续了;

以上两种条件综合,就能计算出股票的最大连续涨停天数了,你学废了吗。

猜你喜欢

HDFS的快照讲解

Hadoop 数据迁移用法详解

Hbase修复工具Hbck

数仓建模分层理论

一文搞懂Hive的数据存储与压缩

大数据组件重点学习这几个

Hive计算最大连续登陆天数的更多相关文章

  1. TSQL--查找连续登陆用户

    --========================================== 需求:有一个用户登陆日志表,记录用户每次登陆时间,然后想查找用户按天连续登陆的情况,找出每次连续登陆的最早时间 ...

  2. 大数据学习day25------spark08-----1. 读取数据库的形式创建DataFrame 2. Parquet格式的数据源 3. Orc格式的数据源 4.spark_sql整合hive 5.在IDEA中编写spark程序(用来操作hive) 6. SQL风格和DSL风格以及RDD的形式计算连续登陆三天的用户

    1. 读取数据库的形式创建DataFrame DataFrameFromJDBC object DataFrameFromJDBC { def main(args: Array[String]): U ...

  3. mysql计算连续天数,mysql连续登录天数,连续天数统计

    mysql计算连续天数,mysql连续登录天数,连续天数统计 >>>>>>>>>>>>>>>>>& ...

  4. PHP计算连续签到天数以及累计签到天数

    代码如下: /** * 统计连续签到天数以及累计签到天数 * @param string $user_long_id 用户ID * @return array 一维数组 */ function sig ...

  5. Redis简单案例(三) 连续登陆活动的简单实现

    连续登陆活动,或许大家都不会陌生,简单理解就是用户连续登陆了多少天之后,系统就会送一些礼品给相应的用户.最常见的 莫过于游戏和商城这些.游戏就送游戏币之类的东西,商城就送一些礼券.正值国庆,应该也有不 ...

  6. js计算日期相差的天数

    在网站开发中,经常会遇到计算日期相差的天数,js 没有提供相应的方法,所以自己写一个,方便将来查看: 代码: function DateDiff(sDate1, sDate2, splitStr) { ...

  7. SQL经典问题:找出连续日期及连续的天数

    create table tmptable(rq datetime) go insert tmptable values('2010.1.1') insert tmptable values('201 ...

  8. php中cal_days_in_month不可用时的替代方法(计算一个月的天数)

    在计算某个月中的天数时,由于PHP编译时没有加上--enable-calendar选项,会导致cal_days_in_month方法不可用. 这时,如果不能更改服务器的编译设置,可以通过以下方法实现该 ...

  9. js返回一组日期中最近连续的天数

    用js获取一组日期(并把当天算入)中连续的天数 刚开始可能想到单纯的比较日期大小判断连续, 而又有大小月,平闰年这些因素,还是时间戳来的安全; 首先得有一组日期,比如: var arr = [ '20 ...

随机推荐

  1. Nginx系列(8)- Nginx安装 | Docker环境下部署

    Docker环境下部署Nginx https://www.cnblogs.com/gltou/p/15186971.html

  2. genymotion启动模拟器后,sdk查询adb devices为空-解决方案

    我们在genymotion中安装了一个安卓模拟器,比如Google Nexus 4,启动该模拟器后,在cmd中输入adb devices,发现为空. 解决方案:在genymotion选择Setting ...

  3. CF803G-Periodic RMQ Problem【离散化,线段树,ST表】

    正题 题目链接:https://www.luogu.com.cn/problem/CF803G 题目大意 一个长度为\(n\)的序列\(a\)复制\(k\)份连接,要求支持 区间赋值 区间查询最小值 ...

  4. P6134-[JSOI2015]最小表示【bitset,拓扑排序】

    正题 题目链接:https://www.luogu.com.cn/problem/P6134 题目大意 给出一张\(n\)个点\(m\)条边的\(DAG\).求联通情况不变的情况下最多删除几条边. \ ...

  5. 技术与艺术的结合,HMS Core让手机主题趣味丛生

    在9月23日晚举办的华为nova9系列新品发布会上,华为在发布nova9系列新机之外,还为观众展示了多款Harmony OS趣味主题.其中一款名为"翻滚吧牛奶"的应用主题看起来十分 ...

  6. 面试官一口气问了MySQL事务、锁和MVCC,我

    面试官:你是怎么理解InnoDB引擎中的事务的? 候选者:在我的理解下,事务可以使「一组操作」要么全部成功,要么全部失败 候选者:事务其目的是为了「保证数据最终的一致性」. 候选者:举个例子,我给你发 ...

  7. IO之字节流

    什么是字节流 像操作 图片 视频 mp4 文档(里面可能有图片) 等等 注意点 必须使用try catch finally 来包 不用throws(流是要关闭的 如果中途抛错 throws 无法将流关 ...

  8. IPtable防火墙概念介绍

    1.iptables安全优化 1.不配外网,做代理转发或者防火墙映射 2.并发过大,不建议开启防火墙 2.防火墙的工作流程: 按照配置规则的顺序自上而下,从前到后进行过滤 如果匹配上新规则,表明是阻止 ...

  9. 无服务计算应用场景探讨及 FaaS 应用实战

    作者 | 宋文龙(闻可)  阿里云全球技术服务部高级交付专家 什么是无服务计算 无服务器计算(Serverless Computing)在构建和运行应用时无需管理服务器等基础设施.它描述了一个细粒度的 ...

  10. pycharm设置文件中显示模板内容

    pycharm中设置自己的文件模板  File>>Settings>>Editor>>File and Code Templates 选择文件类型或者输入文件类型 ...