用HiveQL计算连续天数问题的方法

昨晚简书服务器可能出了什么bug,文章发布出去都会变成完全空白。没办法,只能断更一天,放在今天发了,大概能达到十万字里程碑了吧。

在日常工作中,可能经常会接到业务方类似这样的需求:

  • 统计今年每个用户最长连续签到的天数;
  • 统计最近一个月连续有回帖超过5天的话题;
  • 统计本季度中连续3天以上单日销量超过100的商品。

这种“连续天数”问题看似简单,但实际上对思维能力和编写复杂SQL语句的能力要求比较高。下面以我们曾经接到的一个需求为例,提出解决办法。

有以下简化的日历记录表:

create table user_calendar_record (
  user_id bigint comment '用户ID',
  event_type int comment '记录类型',
  event_data string comment '记录数据',
  upload_time string comment '上传时间'
  del_status int comment '删除状态'
) partitioned by (
  pt_date string comment '记录(分区)日期'
);

现要找出4月间,每个用户类型为24的记录项。如果有用户连续一周及以上记录该项,说明TA对某方面特别重视,应当重点运营。

编写SQL的思路如下。为了避免过多嵌套,所有步骤中都先用子表表示,最后再合成完成的语句。

  1. 以用户ID分组,以记录日期为排序规则,添加一列排名。由于用户每天可以记录不止一次,所以要采用dense_rank()函数,不能用rank()或row_number()。
(
  select user_id,pt_date,
  dense_rank() over(partition by user_id order by pt_date) as date_rank
  from user_calendar_record
  where pt_date >= 20190401 and pt_date <= 20190430
  and event_type = 24 and del_status = 0
) t_a;
  1. 在以上添加了排名的表中,用记录日期减去排名列代表的天数,得到另一个日期。该日期实际上就是一个连续日期序列的第一天日期减去一天(读起来有点拗口,但很容易理解),用它来做标记。
(
  select user_id,pt_date,
  date_sub(pt_date, cast(date_rank as int)) as start_point
  from t_a
) t_b;
  1. 以上表中的user_id和start_point为分组依据,计算每个连续日期序列的天数值。因为数据量不大,所以这里直接用了distinct。数据量大的话还是应该采用group by来代替distinct。
(
  select user_id,start_point,
  count(distinct pt_date) as day_count
  from t_b
  group by user_id,start_point
) t_c;
  1. 最后就可以筛选出天数值最大值>=7的那些记录了。
select user_id,max(day_count) as max_day_count 
from t_c
group by uid
having max(day_count) >= 7;

将上面的4个步骤合起来,就是如下的完整SQL语句了:

select user_id,max(day_count) as max_day_count
from (
  select user_id,start_point,
  count(distinct pt_date) as day_count
  from (
    select user_id,pt_date,
    date_sub(pt_date, cast(date_rank as int)) as start_point
    from (
        select user_id,pt_date,
        dense_rank() over(partition by user_id order by pt_date) as date_rank
        from user_calendar_record
        where pt_date >= 20190401 and pt_date <= 20190430
        and event_type = 24 and del_status = 0
    ) t_a
  ) t_b
  group by user_id,start_point
) t_c
group by user_id
having max(day_count) >= 7;

如果还需要同时得到最大连续天数对应的起始日期怎么办呢?可以将日期计数值存成一张临时表,连续日期最大值存成另一张临时表,然后两表做join就可以得到结果了。SQL语句也就不再赘述。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • 最近公司服务器因为某些原因,导致服务器环境需要全部重新部署,安装nodejs又忘了,记录下,方便下次使用。 安装最...
    Claypot阅读 1,532评论 0 2
  • 1、打开开发者选项, 并启用USB调试,adb shell 或adb devices ,检测不到设备: 方案零:更...
    云层_阅读 1,083评论 0 8
  • 我的故事专栏 这么多年了,我一直窝藏在自己的世界里,窥视着你释放的阳光,偷听着关于你的日常。听说外面爱情在通缉我,...
    番茄拌饭阅读 575评论 6 3
  • 编程未来会成为像驾车一样的技术,每个人都需要懂一点编程。为什么每个人都需要懂一点编程呢? 因为商业的本质是效率。 ...
    李行风阅读 581评论 0 0