SQL连续登录问题(详细案例分析)

如果要统计用户活跃度,那就涉及连续登录问题,接下来将举一个简单的例子来详细说明这个问题:

一、创建一些模拟数据

一些测试数据如下:

deviceid1,2022-10-26,2022-10-26,2022-11-01

deviceid1,2022-10-26,2022-11-03,2022-11-05

deviceid2,2022-10-27,2022-10-27,2022-11-08

deviceid2,2022-10-27,2022-11-10,9999-12-31

deviceid3,2022-10-27,2022-10-27,2022-11-01

deviceid3,2022-10-27,2022-11-04,2022-11-11

deviceid3,2022-10-27,2022-11-14,9999-12-31

deviceid4,2022-10-01,2022-10-01,2022-10-11

deviceid4,2022-10-01,2022-10-13,2022-11-01

deviceid4,2022-10-01,2022-11-03,2022-11-05

sql 复制代码
-- 1.创建用户活跃区间表
create table tmp.app_user_active_range(
  deviceid      string,     -- 设备编号
  first_login   string,     -- 首访日期
  start_dt      string,     -- 用户活跃区间起始时间
  end_dt        string      -- 用户活跃区间结束时间
)
partitioned by(dt string)
row format delimited
fields terminated by ',';

-- 2、模拟用户活跃数据,将上述数据保存到服务器/root/range.txt路径下 然后load到tmp.app_user_active_range表,

load data local inpath '/root/range.txt' overwrite into table  tmp.app_user_active_range partition(dt='2022-11-23');

二、一些统计用户活跃度的问题

下面是三个简单的指标:

1、最近一个月内,每个用户的最大连续活跃天数

2、最近一个月内,连续活跃[1-10)天的人数,[10-20)天的人数,[20+ 天的人数

3、最近一个月内,沉默天数超过3天的有多少人,超过5天有多少人

三、 指标开发详细解决步骤

1、最近一个月内,每个用户的最大连续活跃天数

sql 复制代码
select * from tmp.app_user_active_range;
with t as (
    select *,
       datediff(`if`(end_dt=='9999-12-31',dt,end_dt),`if`(start_dt<date_sub(dt,30),date_sub(dt,30),start_dt))+1 active_days
       from tmp.app_user_active_range where end_dt>=date_sub(dt,30)
    union
    select *,0 from tmp.app_user_active_range where end_dt<date_sub(dt,30)
)select deviceid,max(active_days) max_days from t group by deviceid;

2、最近一个月内,连续活跃[1-10)天的人数,[10-20)天的人数,[20+ 天的人数

sql 复制代码
-- 需求2:最近一个月内,连续活跃[1-10)天的人数,[10-20)天的人数,[20+ 天的人数
with t as (
    select *,
       datediff(`if`(end_dt=='9999-12-31',dt,end_dt),`if`(start_dt<date_sub(dt,30),date_sub(dt,30),start_dt))+1 active_days
       from tmp.app_user_active_range where end_dt>=date_sub(dt,30)
    union
    select *,0 from tmp.app_user_active_range where end_dt<date_sub(dt,30)
),t1 as (
    select deviceid,
        case when active_days between 1 and 9 then '[1-10)'
             when active_days between 10 and 19 then '[10-20)'
             when active_days>=20 then '[20+'
             else '0'
        end as qujian
        from t
)select qujian,count(distinct deviceid) people_num from t1 group by qujian;

3、最近一个月内,沉默天数超过3天的有多少人,超过5天有多少人

sql 复制代码
-- 最近一个月内,沉默天数超过3天的有多少人,超过5天有多少人

-- 最终结果
with  z as (
    -- 前半段沉默时间和中间沉默时间
    with t as (
   select *,
       datediff(start_dt,lag(end_dt,1,`if`(first_login<date_sub(dt,30),date_sub(dt,30),first_login)) over(partition by deviceid order by start_dt))-1 chenmodays
       from tmp.app_user_active_range where end_dt>=date_sub(dt,30)
)select deviceid,chenmodays from t where chenmodays>0
union all
-- 后半段沉默时间
select deviceid,datediff(dt,end_dt)-1 chenmodays from (
    select *,max(end_dt) over(partition by deviceid) max_chenmo from tmp.app_user_active_range where end_dt>=date_sub(dt,30)
    )t where max_chenmo<dt and end_dt=max_chenmo
) ,z2 as (
    select deviceid,sum(chenmodays) chenmodays from z group by deviceid
) select
         case when chenmodays>=3 and chenmodays<5 then '[3,5)'
              when chenmodays>5 then '[5+)'
              else '[0,3)'
         end flag,
         count(1) num
         from z2 group by flag;
相关推荐
余槐i5 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
数据库小学妹5 小时前
PostgreSQL表膨胀怎么办?autovacuum清不动的根因与排查命令
数据库·postgresql·表膨胀·mvcc·数据库运维
mister_guo5 小时前
MySQL-1267错误:排序规则冲突的原因与解决方案
数据库·mysql
骇客野人6 小时前
在麒麟操作系统上 分别安装 jdk1.8, 达梦数据库,redis ,memcache 的操作实施方案和步骤
数据库·redis·memcached
美狐美颜SDK开放平台8 小时前
直播APP如何实现美白滤镜功能?视频美颜SDK技术开发方案详解
前端·数据库·人工智能·音视频·美颜sdk·直播美颜sdk·视频美颜sdk
花间相见9 小时前
【计算基础|MySQL01】【上手】安装连接、数据类型与建库建表
数据库·后端
花间相见9 小时前
【计算基础|MySQL02】【上手】SQL 增删改查
数据库·后端
ITxiaobing20239 小时前
IP 库与 AppsFlyer 国家/地区数据不一致,如何系统地对账?
数据库·网络协议·tcp/ip
这个DBA有点耶10 小时前
从时间到语义:时序数据库与向量数据库的核心机制、选型与多模融合趋势
数据库·mysql·架构
对空六课10 小时前
RFM分层边界变化的回溯计算
大数据·服务器·前端·数据库·人工智能·算法·数据分析