hive sql实战案例-最高连续签到天数

问题描述

求每个用户的最高连续签到天数
在这里插入图片描述

分析问题

问题的关键是给用户的连续签到做出标记,然后在按照用户和连续签到标记进行分组聚合就可以。

准备数据

-- 删表
drop table if exists signs;

-- 建表
CREATE TABLE signs(
  user_name string COMMENT '姓名',
  sign_date string comment '签到日期'
);
  
-- 插入数据 
insert overwrite table signs values
('老王','2021-01-01'),
('老王','2021-01-02'),
('老王','2021-01-03'),
('老王','2021-01-07'),
('小张','2021-01-01'),
('小张','2021-01-03'),
('小张','2021-01-04');

-- 查询数据
select * from signs;

方案1 日期减排序

第一步:给每一组连续签到打标,方法是签到日期减去排名,如果是连续签到,返回的日期相同。比如老王1号、2号、3号连续签到,返回2020-12-31。

  select user_name
  ,sign_date
  ,rank() over(partition by user_name order by sign_date asc) as `排名`
  ,date_sub(sign_date, rank() over(partition by user_name order by sign_date asc))as label  -- 连续签到分组标签
  from signs
  order by user_name,sign_date

在这里插入图片描述
第二步:统计每个用户连续签到天数,并取出最大值

with t1 as (
     -- 给每个用户每次连续签到打标签
      select user_name
      ,sign_date
      ,rank() over(partition by user_name order by sign_date asc) as `排名`
      ,date_sub(sign_date, rank() over(partition by user_name order by sign_date asc))as label  -- 连续签到分组标签
      from signs
      order by user_name,sign_date 
),
t2 as (
  -- 统计每个用户每次连续签到的次数
	select user_name
  ,label -- 连续签到分组标签
  ,count(distinct sign_date) as days
  from t1
  group by user_name,label
  
)
-- 取每个用户的最大天数
select user_name
,max(days) as days
from t2
group by user_name

方案2 lag判断

1、找到每个用户前一天的签到日期

-- 查询数据
select user_name
,sign_date
,lag(sign_date,1) over(partition by user_name order by sign_date) as sign_d1
from signs

在这里插入图片描述
2、当sign_d1为空或者日期差大于1时,赋值为1 否则为0

with  t1 as (
    -- 
    select user_name
    ,sign_date
    ,lag(sign_date,1) over(partition by user_name order by sign_date) as sign_d1
    from signs
)
,t2 as (

    select t1.*
    ,case
    when sign_d1 is null then 1 
    when datediff(sign_date,sign_d1) >1 then 1 
    else 0 end as label
    from t1

)
select * from t2

在这里插入图片描述

3、使用sum over滚动求和,这样就标记出了连续签到的分组

with  t1 as (
    -- 查询数据
    select user_name
    ,sign_date
    ,lag(sign_date,1) over(partition by user_name order by sign_date) as sign_d1
    from signs
)
,t2 as (

    select t1.*
    ,sum(case
    when sign_d1 is null then 1 
    when datediff(sign_date,sign_d1) >1 then 1 
    else 0 end) over(partition by user_name order by sign_date) as label
    from t1

)
select * from t2

在这里插入图片描述
3、按照用户和连续签到标记聚合,求出每个用户每次连续签到天数

with  t1 as (
    -- 查询数据
    select user_name
    ,sign_date
    ,lag(sign_date,1) over(partition by user_name order by sign_date) as sign_d1
    from signs
)
,t2 as (

    select t1.*
    ,sum(case
    when sign_d1 is null then 1 
    when datediff(sign_date,sign_d1) >1 then 1 
    else 0 end) over(partition by user_name order by sign_date) as label
    from t1

)
,t3 as (
  -- 按照用户和连续签到标记聚合
  select user_name,label
  ,count(distinct sign_date) as days
  from t2 
  group by user_name,label

)
select * from t3

在这里插入图片描述
4、按照用户聚合,求出每个用户连续签到天数的最大值

with  t1 as (
    -- 查询数据
    select user_name
    ,sign_date
    ,lag(sign_date,1) over(partition by user_name order by sign_date) as sign_d1
    from signs
)
,t2 as (

    select t1.*
    ,sum(case
    when sign_d1 is null then 1 
    when datediff(sign_date,sign_d1) >1 then 1 
    else 0 end) over(partition by user_name order by sign_date) as label
    from t1

)
,t3 as (
  -- 按照用户和连续签到标记聚合
  select user_name,label
  ,count(distinct sign_date) as days
  from t2 
  group by user_name,label

)
,t4 as (
 -- 求出每个用户最高连续签到天数
 select user_name,max(days) as days
 from t3
 group by user_name
)
select * from t4

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值