前言

众所周知,产品数据监控体系中,用户留存是一个非常重要的指标,细化到业务场景中,留存其实可以拆解出来多个类别:包括新增用户留存、活跃用户留存、付费用户留存、回流用户留存、新增付费用户留存、回流付费用户留存等等,以下主要针对活跃用户留存设计ClickHouse查询语句。

表结构及查询需求

表结构

time user_id
January 1, 2021, 08:33 AM 112233abc
January 1, 2021, 09:00 AM 221133bac
January 1, 2021, 09:20 AM 113322acb
January 2, 2021, 10:12 AM 113322acb
January 2, 2021, 11:01 AM 221133bac
January 3, 2021, 11:45 AM 112233abc
…… ……

查询需求:在表 User_login 中,按指定时间区间给出该区间内每日的活跃次留、三留、七留、十四留、三十留。

ClickHouse语句如何实现

PS:涉及多重嵌套查询

  1. 查询每个 user_id 的登录时间间隔(按天),按日期分组,得到每个 user_id 两次登录的时间差;
select uid,base_date,retention_date
from -- 表a,首日登录的用户(select distinct date(time) base_date, user_id uidfrom User_loginwhere -- 需要计算留存的日期区间base_date between '2021-03-01' and '2021-03-31'group by uid,base_date) a
left join-- 表b,表连接匹配后续登录的情况,计算留存(select distinct date(time) retention_date, user_id uidfrom User_loginwhere -- 此处不应限制最大日期,否则可能导致后续留存率为0retention_date >= '2021-03-01'group by uid,retention_date) b
on a.uid = b.uid
where -- 保证每条记录不会连接到在当前记录时间之前的数据,如昨天的登录base_date <= retention_date
order by uid,base_date

结果如下(demo数据):

  1. 利用 retention_date 减去 base_date 得到两日登录的日期差值;
select uid,base_date,retention_date,retention_date - base_date datediff
from /* 上一步的查询(select uid,base_date,retention_datefrom -- 表a,首日登录的用户(select distinct date(time) base_date, user_id uidfrom User_loginwhere -- 需要计算留存的日期区间base_date between '2021-03-01' and '2021-03-31'group by uid,base_date) aleft join -- 表b,表连接匹配后续登录的情况,计算留存(select distinct date(time) retention_date, user_id uidfrom User_loginwhere -- 此处不应限制最大日期,否则可能导致后续留存率为0retention_date >= '2021-03-01'group by uid,retention_date) bon a.uid = b.uidwhere -- 保证每条记录不会连接到在当前记录时间之前的数据,如昨天的登录base_date <= retention_dateorder by uid,base_date) c*/
order by uid,base_date

结果如下(demo数据):

  1. 对应提取相应的两次登录的日期差,得到当日、次日、三日、七日等多个登录用户数的值;
select base_date,sum(case when datediff = 0 then 1 else 0 end) day_0,sum(case when datediff = 1 then 1 else 0 end) day_1,sum(case when datediff = 2 then 1 else 0 end) day_2,sum(case when datediff = 6 then 1 else 0 end) day_6,sum(case when datediff = 13 then 1 else 0 end) day_13,sum(case when datediff = 29 then 1 else 0 end) day_29
from /* 上一步的查询(select uid,base_date,retention_date,retention_date - base_date datedifffrom (select uid,base_date,retention_datefrom -- 表a,首日登录的用户(select distinct date(time) base_date, user_id uidfrom User_loginwhere -- 需要计算留存的日期区间base_date between '2021-03-01' and '2021-03-31'group by uid,base_date) aleft join -- 表b,表连接匹配后续登录的情况,计算留存(select distinct date(time) retention_date, user_id uidfrom User_loginwhere -- 此处不应限制最大日期,否则可能导致后续留存率为0retention_date >= '2021-03-01'group by uid,retention_date) bon a.uid = b.uidwhere -- 保证每条记录不会连接到在当前记录时间之前的数据,如昨天的登录base_date <= retention_dateorder by uid,base_date) corder by uid,base_date) d*/
group by base_date
order by base_date

结果如下(demo数据,一共查询出31天每天的各个留存情况,其中day_0是当日的登录):

  1. 利用次日、三、七日等登录数除以当日登录数,得到对应留存率;
select base_date,-- 保留4位小数,用于百分比展示round(day_1/day_0, 4) retention_2,round(day_2/day_0, 4) retention_3,round(day_6/day_0, 4) retention_7,round(day_13/day_0, 4) retention_14,round(day_29/day_0, 4) retention_30
from /* 上一步的查询(select base_date,sum(case when datediff = 0 then 1 else 0 end) day_0,sum(case when datediff = 1 then 1 else 0 end) day_1,sum(case when datediff = 2 then 1 else 0 end) day_2,sum(case when datediff = 6 then 1 else 0 end) day_6,sum(case when datediff = 13 then 1 else 0 end) day_13,sum(case when datediff = 29 then 1 else 0 end) day_29from (select uid,base_date,retention_date,retention_date - base_date datedifffrom (select uid,base_date,retention_datefrom -- 表a,首日登录的用户(select distinct date(time) base_date, user_id uidfrom User_loginwhere -- 需要计算留存的日期区间base_date between '2021-03-01' and '2021-03-31'group by uid,base_date) aleft join -- 表b,表连接匹配后续登录的情况,计算留存(select distinct date(time) retention_date, user_id uidfrom User_loginwhere -- 此处不应限制最大日期,否则可能导致后续留存率为0retention_date >= '2021-03-01'group by uid,retention_date) bon a.uid = b.uidwhere -- 保证每条记录不会连接到在当前记录时间之前的数据,如昨天的登录base_date <= retention_dateorder by uid,base_date) corder by uid,base_date) dgroup by base_dateorder by base_date*/

结果如下(demo数据):

到这里所有活跃留存就查询完毕了,百分比的显示只需在metabase设置中调整一下即可,效果如下:

emmm…总感觉还是差点啥,是的没错!还有一环!!

  1. 增加日期选择交互框,按指定日期进行查询;

这也是最后一步了,如果在编写查询语句时就把查询时间写死了,当业务方想在平台上查看留存时,还得专门找数据小伙伴来调整时间,这不仅给数据侧带来更多工作量,还降低了业务方工作效率;

如果不限制这个时间,则每次查询都要把整个数据表都过一遍,这就不仅影响到查询效率了,当数据量日渐增多,这查询语句也会给数据库带来越来越大的压力;

因此可以使用时间筛选交互框的方式,让业务方自己选择想要查看的日期区间对应的留存情况,操作如下:(在日期筛选时把条件设为 {{date}} 形式,再在设置里将交互框调整为日期类型即可)

select base_date,-- 保留4位小数,用于百分比展示round(day_1/day_0, 4) retention_2,round(day_2/day_0, 4) retention_3,round(day_6/day_0, 4) retention_7,round(day_13/day_0, 4) retention_14,round(day_29/day_0, 4) retention_30
from (select base_date,sum(case when datediff = 0 then 1 else 0 end) day_0,sum(case when datediff = 1 then 1 else 0 end) day_1,sum(case when datediff = 2 then 1 else 0 end) day_2,sum(case when datediff = 6 then 1 else 0 end) day_6,sum(case when datediff = 13 then 1 else 0 end) day_13,sum(case when datediff = 29 then 1 else 0 end) day_29from (select uid,base_date,retention_date,retention_date - base_date datedifffrom (select uid,base_date,retention_datefrom -- 表a,首日登录的用户(select distinct date(time) base_date, user_id uidfrom User_loginwhere -- 需要计算留存的日期区间-- 利用时间选择交互,手动选择时间区间后再运行base_date between {{start_date}} and {{end_date}}group by uid,base_date) aleft join -- 表b,表连接匹配后续登录的情况,计算留存(select distinct date(time) retention_date, user_id uidfrom User_loginwhere -- 此处不应限制最大日期,否则可能导致后续留存率为0retention_date >= {{start_date}}group by uid,retention_date) bon a.uid = b.uidwhere -- 保证每条记录不会连接到在当前记录时间之前的数据,如昨天的登录base_date <= retention_dateorder by uid,base_date) corder by uid,base_date) dgroup by base_dateorder by base_date)

效果如下:





ClickHouse应用随笔2——活跃用户留存统计(前方高能~~)相关推荐

  1. 用户留存统计 java_用户留存率以及DNU、DAU、WAU、MAU关系

    名词解释: 用户留存率:在互联网行业中,用户在某段时间内开始使用应用,经过一段时间后,仍然继续使用该应用的用户,被认作是留存用户.这部分用户占当时新增用户的比例即是留存率,会按照每隔1单位时间(例日. ...

  2. redis 用setbit(bitmap)统计活跃用户

    getspool.com的重要统计数据是实时计算的.Redis的bitmap让我们可以实时的进行类似的统计,并且极其节省空间.在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的 ...

  3. redis位图法bitmap统计活跃用户

    位图法 位图(bitmap),就是用位(bit)来表示存放的某种状态,如开关,有无.在redis中,字符串是以二进制的形式存储的,因此位图在redis中并不是一种数据类型,而是一种字符串的表现形式.位 ...

  4. redis实现用户签到,统计活跃用户,用户在线状态,用户留存率

    开发的过程中,可能会遇到用户签到.统计当天的活跃用户.以及每个用户的在线状态,用户留存率的开发需求,可能会用传统的方法,根据相应的需求设计数据库表等,但这样耗费的存储空间大,以及性能方面也不会太好,下 ...

  5. 数据统计之日活跃用户统计

    日活跃用户统计 接口分析 请求方式:GET /meiduo_admin/statistical/day_active/ # 日活跃用户统计url(r'^statistical/day_active/$ ...

  6. redis服务器信息统计,利用Redis统计网站在线活跃用户的方法

    前言 在工作中我们经常遇到这样的需求,要对某个在线网站的活跃用户数量进行统计.这里我们以redis为例,说明一下其实现的过程. 实现方法 在Redis中存在bitmap这种数据类型,这种数据类型是建立 ...

  7. 后台管理系统、商品管理、商品发布、商品回收、订单管理、退款管理、运营管理、商城设置、导航分类、营销管理、优惠券套餐、数据统计、活跃用户、数据埋点、财务管理、对账单、财务数据、账户资产、电商后台

    后台管理系统.商品管理.商品发布.商品回收.订单管理.退款管理.运营管理.商城设置.导航分类.营销管理.优惠券套餐.数据统计.活跃用户.数据埋点.财务管理.对账单.财务数据.账户资产.账号管理.电商后 ...

  8. 华为推送服务 | 简单一招,提高用户活跃和留存

    如今互联网红利见顶,拉新成本逐渐增高,与此同时,用户花在某个特定应用的时间也越来越少.据<2019年Q4移动互联网行业数据研究报告>指出,过去一年里,移动网民人均安装APP总量持续增长至6 ...

  9. 【备忘】es统计用户留存数据,公式都一样,语句和mysql区别很大

    //es统计用户留存数据,公式都一样,语句和mysql区别很大 {"query": {"bool": {"must": [{"ra ...

最新文章

  1. 洛谷 P1865 A % B Problem[筛素数/前缀和思想/区间质数个数]
  2. 036、Linux下ipmitool命令
  3. oracle 10G windows启动与关闭另类方法
  4. matlab运行dxcv,MATLAB imresize 函数和 OpenCV resize 函数结果不同
  5. python模拟登陆163邮箱并获取通讯录
  6. 【Elasticsearch】Elasticsearch 索引生命周期管理
  7. mysql批量插入之提高插入效率
  8. 【图像隐写】基于matlab FFT数字水印嵌入【含Matlab源码 1670期】
  9. c语言i=5.6a=(int)i,(PSIM仿真)从零开始设计BOOST数字控制器
  10. 陈越微博c语言自学攻略,数据结构自学攻略
  11. 加权平均成本计算公式
  12. 蓝墨云班课在计算机应用基础的教学,蓝墨云班课在“计算机应用基础”课程教学中的应用效果分析...
  13. 家庭收支记账软件项目【Golang-面向过程】
  14. FTP服务器的搭建,可两个电脑通过局域网进行传输
  15. 2019冬季PAT甲级
  16. hbase踩坑记录(二):Can not resolve promote.cache-dns.local, please check your network
  17. 安装Tomcat步骤
  18. Tensorflow faster RCNN目标检测车牌
  19. Transform 3.1 用户手册(SPSS 的通用数据转换程序)
  20. 批量挖sql注入漏洞

热门文章

  1. Ubuntu LinuxMint安装微信QQ阿里旺旺
  2. 相关方参与度评估矩阵
  3. 纬编针织脱圈走纱分析与防走纱工艺研究
  4. 1. 可视化的前世今生
  5. mini2440nbsp;裸奔dm9000(上)
  6. Acme CAD Converter 2015 8.7.0.1440 Multilingual 1CD CAD图形文件转换和查看软件
  7. 人工智能 其实还有点“笨”
  8. solr group分组查询
  9. QIUXP-预训练语言模型:BertMarker:MarkBERT: Marking Word Boundaries Improves Chinese BERT
  10. BibTeX 定制自己的参考文献模板 bst