Leetcode 1454题: Active Users (连续5天登录的用户)

题目描述

这是一道非常经典的问题,连续n天登录的用户。之前在面试的时候也有被问到过,但是当时答的不好,这里在leetcode里再次碰到,所以做个总结,leetcode中问的是连续5天,但是我们希望将其拓展到连续n天。

以下是题目中的原始表
第一张是用户表,id列为主键。
在这里插入图片描述
第二张表为登录信息,因为其中包含重复行,表示一个用户在同一天多次登录,所以这张表无主键。
在这里插入图片描述

思路

说实话,第一次遇到这个问题,我是懵逼的,唯一想到的方法就是创建多张子表,每张表的日期依次向前推一天,然后多表连接。但是这种方法显然低效。同时,并不能解决任意天数n的情况,比如连续100天,总不能去创建100张子表吧?

OK,那么还有什么优雅的解法呢?

这里需要用到一个 row_number()方法,对每个用户的登录日期(去重后)按日期先后进行标号,然后用日期去减去这个标号。如果是一系列连续的日期,标号也是一系列连续递增的数,那么相减(日期减去对应标号)之后的结果就应该是相同的。然后我们对结果去进行count(),如果对于某个用户相同值的count大于等于n,那么就意味这这个用户存在连续n天登录。

以下是具体代码。

select Accounts.name
from
(select distinct id,res from (select id,date_sub(login_date,interval cum day) res  from (select *,row_number() over(partition by id order by login_date) as cum from (select distinct login_date,id from Logins) as t0) as t1) as t2 group by id,res having count(*)>=5) as t3
left join
Accounts
on t3.id=Accounts.id;

稍微做下说明:
t1表得到的结果就是对每个用户进行按日期标号
t2表得到的结果就是根据t1表中的日期和标号,进行相减得到res
t3表就是根据t2表得到的相减结果res和用户id去进行group by 并筛选出count大于5的内容。

最后利用用户id和Accounts表连接,得到对应用户的名字。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值