背景
数据运营人员常常会需要查找活跃用户名单,而活跃用户很多情况下被定义为连续在线或发单n天及以上的用户。一方面我们可以根据n的值直接进行筛选;更具一般性地,就要求我们去求取每个用户某段时间内的最大连续在线或者发单天数了。

SQL求连续在线天数是一个非常经典的问题,该问题在不考虑计算成本下有非常多的解法。该问题也是我在面试实习生时最喜欢深入问的一个问题,在引导一个候选人去完成这个问题的过程中可以看出其对sql的理解深度以及其思维是否灵敏。

该问题的最大难点在于如何判断日期与日期间是否连续,那这就要涉及到处理行与行之间的关系了。说到这对SQL比较熟悉的同学应该就会反应出使用join或者窗口函数来处理了。

数据:
假设我们有19年一月份每日用户发单数据存储于订单表order_base:

user_id       order_id       create_time
234520012   1231512416323   2019-01-02 12:21:11
123149908   2412298719221   2019-01-04 01:11:34…            …                   …

解法1(通过与特定日期的日期差判定连续):
本方法比较tricky。连续的时间以为着这些时间点与某一个特定时间点的时间差也是连续的,从下表可以直观理解这一点:

日期               特定日期        日期差d
2019-01-01      2019-01-01      0
2019-01-02      2019-01-01      1
2019-01-04      2019-01-01      3
2019-01-05      2019-01-01      4
2019-01-06      2019-01-01      5

那么我们对该日期差d进行个排序,如果连续的话,d与序号的差值应该是相同的,如下表:

 日期           特定日期   日期差d      序号r   日期差d与序号r的差值
2019-01-01      2019-01-01      0       0       0
2019-01-02      2019-01-01      1       1       0
2019-01-04      2019-01-01      3       2       1
2019-01-05      2019-01-01      4       3       1
2019-01-06      2019-01-01      5       4       1

这样答案就显而易见了,只需要对上面这个子查询的最后一列进行分组统计行数,变得到了每次连续的天数,再取连续天数的最大值,便是我们想要的答案。

selectuser_id,max(date_cnt) as max_continuation_date_cnt
from
(selectuser_id,d-d_ranking as d_group, -- 连续日期的组标记count(1) as date_cntfrom (selectuser_id,d, --与标记日期的日期差row_number() over(partition by user_id order by d) as d_ranking --与标记日期的日期差的排序from(selectuser_id,datediff(create_date,'2019-01-01') as d --与标记日期的日期差from(selectuser_id,to_date(create_time) as create_datefromorder_basegroup byuser_id,date(create_time))a -- 在这一层获取用户的发单日期并去重)b --这一层获取与标记日期的日期差)c --获取连续日期的排序group byuser_id,d-d_ranking
)d -- 获取每一个连续日期组的连续天数
group byuser_id

解法2(left join进行笛卡尔积):
假设我们不需要知道用户最大的连续天数,只需要知道某个用户是否出现连续n天(假设n为3)登录的行为。那这里首先给出一种完全不考虑计算复杂度的解法,使用纯join关联去实现该问题。

整体思路是去获得同一个用户的发单日期对,看每一个发单日期的n天内是否有n个发单日期。

selectuser_id
from
(selectuser_id,to_date(create_time) as create_datefromorder_basegroup byuser_id,date(create_time)
)a -- 在这一层获取用户的发单日期并去重
left join
(selectuser_id,to_date(create_time) as create_datefromorder_basegroup byuser_id,to_date(create_time)
)b -- 与a完全相同的逻辑,为了得到日期与日期间的关联
ona.user_id = b.user_id --仅使用user_id进行关联,获取同一个用户发单日期间的笛卡尔积
wherea.create_date <= b.create_dateand date_add(a.create_date,3) > b.create_date --以a的日期为基准,保留从a.create_date开始的3天内发单日期
group byuser_id,a.create_date
havingcount(1) = 3 --如果从a.create_date开始的3天内都有发单,则应该有3条记录

该方法容易理解,但其最大的弊端在于关联时造成的笛卡尔积大大增加了计算的复杂度。在较小的数据集上可以考虑该方法,但实际生产环境下意义并不大。

解法3 (lead或lag):
最后介绍一个最为直观,也是计算成本最小的方法。假设我们需要求连续登陆n天(假设n为7)及以上的用户,那么对于一个存在该行为的用户,他去重和排序后的发单日期信息中,必存在某一天,往前回溯(往后推)6条记录的日期,等于该日期减6(加6)。这么说可能不太好理解,但相信你看了以下代码便能很快明白我在说什么:

selectuser_id
from
(selectuser_id,create_date,lag(create_date,6,null) over(partition by user_id order by create_date) as last_6_row -- 按时间排序后6行之前的那一条记录(selectuser_id,to_date(create_time) as create_datefromorder_basegroup byuser_id,date(create_time))a -- 在这一层获取用户的发单日期并去重
)b --获取6行之前的那一条记录
wheredatediff(create_date,last_6_row) = 6
group byuser_id

转载https://blog.csdn.net/Adrian_Wang/article/details/89791948

Hive SQL— 连续发单天数相关推荐

  1. Hive_HQL_复杂SQL_连续发单天数

    原文地址: 1.Hive SQL复杂场景实现(1) -- 连续发单天数 https://blog.csdn.net/Adrian_Wang/article/details/89791948 至今在数据 ...

  2. Hive SQL复杂场景实现(1) —— 连续发单天数

    本文同时发表于我的个人博客http://xinyuwg.com,访问该链接以获得详细信息与更好的阅读体验. 本文为原创内容,未经允许请勿转载. 至今在数据分析岗摸爬滚打已有一年,尚且不敢说自己挖掘洞见 ...

  3. Hive sql : 查询连续登录天数

    查询连续登录天数 1.问题描述 2.在Hive中建表 3.查询最大连续登录天数 1.问题描述 目前有两列数据,分别是用户ID和用户登录的时间,现需要统计用户连续登录的最大天数,中间如有断开,则不算连续 ...

  4. sql server计算日期到当前日期天数_Excel如何统计连续停机天数问题

    前几天有个朋友问了一个关于连续时间统计的问题,使用Power Query for Excel来解决的.今天在张俊红老师的公众号上看到了使用使用SQL来解决连续时间的统计问题.这个问题是一个非常经典的例 ...

  5. SQL计算QQ连续登陆天数

    最近遇到一个SQL查询需求:计算QQ连续登陆天数? 连续登陆天数不间断,如果有一天没登陆就重新计算. 数据准备 mysql> create table user_login(user_id in ...

  6. Hive SQL经典面试题:统计连续登陆的三天及以上的用户

    Hive SQL经典面试题 最近发现一道大数据面试经常会问的SQL题目:统计连续登录的三天及以上的用户(或者类似的:连续3个月充值会员用户.连续N天购买商品的用户等),下面就来记录一下解题思路. 要求 ...

  7. HIVE面试题原理详解 统计用户连续交易的总额、连续登陆天数、连续登陆开始和结束时间、间隔天数

    HIVE面试题原理详解 统计用户连续交易的总额.连续登陆天数.连续登陆开始和结束时间.间隔天数 友情提示 创建数据表 添加数据 流程图 第一步分析(子表a) 第二步分析(子表b) 第三步分析(子表c) ...

  8. SQL——最大连续登录天数、当前连续登录天数、最大连续未登录天数问题、连续登陆N天用户、连续座位号

    问题: 最大连续登录天数 当前连续登录天数 最大连续未登录天数 连续登陆3天用户(三种方法) 选出连续座位的编号 前三个问题所用数据: 原数据表:user_active表 表字段:用户.新增日期.活跃 ...

  9. SQL求用户的最大连续登陆天数

    建表插入数据 create table tmp_continous (id STRING ,time DATETIME );INSERT OVERWRITE TABLE tmp_continous S ...

最新文章

  1. python判断两个值是否相等_Python--比较两个字典部分value是否相等
  2. python day29
  3. 蛋白质折叠的霰弹枪方法
  4. 2030年,逾1亿中国人需要学习新技能并转换岗位,这就是摩擦性失业
  5. WM-Tcode集合
  6. pythondocx文档重叠_使用PYTHON实现docx文档的读写
  7. 网络工程:3.1 RIP(Routing Information Protocol)协议
  8. Docker 常用命令,还有谁不会?
  9. 5.4万Star全部归零,项目作者:十分后悔
  10. 【转】Oracle 系统权限详细列表
  11. Altium Designer 09简易教程(一)
  12. 信息学奥赛c++ 初学保姆级教程
  13. matlab常数模块,simulink怎样输入常数
  14. 任务栏-IDEA图标变白色
  15. 华为机试二星题--机器人走迷宫
  16. 仅10天修复3个零日漏洞 苹果是真的拼了命
  17. 【Office】Visio无响应问题(打开形状样式功能区即卡死)的解决方案
  18. 水果店怎么搞活动方案,水果店促销活动方案
  19. [AD资料] AD入门之AD10软件安装
  20. [数据分析笔记] 网易云歌单分析系列02—pyecharts柱状图

热门文章

  1. Scrapy学习第四课
  2. C语言学习总结(三)-----函数指针
  3. Android P (9.0)刘海屏(DisplayCutout)适配方法
  4. C++primeplus P368-P391
  5. Java社交商城APP+小程序多功能B2B2C商城源码
  6. 家用计算机做raid有用吗,磁盘阵列是什么?家用有必要磁盘阵列吗
  7. (详细)《美国节日》:某月的第几个星期几
  8. 06-树(tree)
  9. 共享企业文化造就企业明天
  10. bilibili缓存文件在哪里_都9012了,听说你还不了解缓存?