SQL连续问题

在日常工作或者面试时,我们经常会遇到这样的问题,比如:“统计下用户最长连续登录的天数”,“统计下连续登录超过10天的用户”,“统计下连续3天交易额超过100W的店铺”。这种问题,其实都是一个套路,我们这里简单介绍一种解决思路。

用户连续登录天数

我们先来看下用户连续登录问题,我们简化下数据,只保留用户ID和登录时间:

其实做数据来说,我们的思路一定要清晰,知道我们要什么样的数据,就像这个连续问题,如果我们知道怎样来判断连续,只要再转化成SQL就行了。所以,我们先思考下,怎样来判断用户是不是连续登录。

连续其实就是这样,我今天登录了,然后昨天也登录了,说明我就连续两天登录了,我们也经常会在APP或者网站上遇到什么签到领积分,签到多少天领奖品之类的,其实都是产品为了提高日活提高用户留存的套路。

1.根据上次登录日期判断

我们回过头,继续看这个连续的问题,上面的数据已经有了,如果要手工判断用户登录是否连续的话,会怎样来呢?比如,用户今天登录了,我们只需要用户上一次登录是什么时候就可以了,如果用户昨天也登录了,就说明用户是连续登录第2天了,所以,我们将数据处理一下。

现在我们有了用户本次登录日期和上次登录日期,只要用户本次登录和上次登录的间隔天数是1,就说明用户连续登录了,我们来看看

这样,我们就可以看到,我们根据本次登录时间和上次登录时间,计算出间隔天数,间隔为1的都是连续的日期,首次登录的时候,我们可以填入默认值0。这样看上去标注黄色的都是连续的日期,但是要注意,第一个标黄的日期表示2天。那我们该怎样统计出用户每次连续的天数呢?如果只把间隔天数为1的记录拿出来,好像又没有办法统计哪些天是连续一起的,我们再对这个间隔天数做个排序


这样,我们根据排序的序号,就可以将间隔天数为1的记录拿出来聚合了。

下面我们就需要将上面的想法转化成SQL:

由于我们要使用mysql,mysql中没有开窗函数,写起来很麻烦,需要多次使用变量;

pg版可以参考之前的文章:SQL笔试题-连续登录天数

-- 1. 获取间隔天数

-- 初始化变量

set @pre_login_date:=null,@pre_user_id:=null;

drop table if exists tmp_20180415_1;

create table tmp_20180415_1 as

select

user_id,

login_date,

pre_login_date,

-- 计算本次登录和上次登录的差值

coalesce(datediff(login_date,pre_login_date),0) as diff_days

from (

select

-- 当前记录

user_id, -- 当前user_id

login_date, -- 当前login_date

-- 上一条记录

@pre_user_id as pre_user_id,

if(@pre_user_id=user_id , @pre_login_date , null) as pre_login_date,

-- 初始化上一条记录

@pre_login_date:=login_date as cur_login_date,

@pre_user_id:=user_id  as cur_user_id

from

tm_login_log

order by

user_id,login_date

) x

order by user_id,login_date;

-- 2.对间隔天数进行排序

set @pre_user_id:=null,@pre_diff_days:=0,@rn:=1;

select

user_id,rn , min(pre_login_date) as from_login_date,max(login_date) as to_login_date

from (

select

user_id,

login_date,

pre_login_date,

diff_days,

if(@pre_user_id=user_id,if(@pre_diff_days=diff_days,@rn:=@rn,@rn:=@rn+1),@rn:=1) as rn,

@pre_user_id:=user_id,

@pre_diff_days:=diff_days

from tmp_20180415_1

order by user_id,login_date

) x

where diff_days=1

group by user_id,rn;


结果时这样的,用户ID和他连续登录的日期,但是这个rn并没有什么用,如果要看连续登录天数的话,我们可以重新根据开始时间和结束时间进行计算。继续延伸的话,我们还可以统计用户最长的登录天数。


2.根据登录日期排序

还有一种类似的思路,就是首先根据登录日期排序,这样我们获得的排序序号就是连续的,然后再统计每个登录日期和一个初始日期的间隔天数,如果登录连续的话,2个值相减之后也可以用来判断是否连续。


感兴趣的同学可以试试MySQL的实现。

后记

其实大家主要了解思路就行了,使用mysql来实现,比较麻烦,不会写也没问题,当然应该还有更简便的方法,只是我还没有想到。在日常工作中,其实还有很多别的方式来更方便的实现,比如,我们可以创建一张用户每天登录的表,然后在刷新当天数据的同时,去判断昨天该用户有没有登录,有的话则计入连续;Hive中也支持各种开窗函数,写起来很简单。

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

推荐阅读更多精彩内容