# Write your MySQL query statement below
1454. 活跃用户
表 Accounts
:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | name | varchar | +---------------+---------+ id 是该表主键(具有唯一值的列) 该表包含账户 id 和账户的用户名.
表 Logins
:
+---------------+---------+ | Column Name | Type | +---------------+---------+ | id | int | | login_date | date | +---------------+---------+ 该表可能包含重复项. 该表包含登录用户的账户 id 和登录日期. 用户也许一天内登录多次.
活跃用户 是指那些至少连续 5 天登录账户的用户。
编写解决方案, 找到 活跃用户 的 id 和 name。
返回的结果表按照 id
排序 。
结果表格式如下例所示。
示例 1:
输入: Accounts 表: +----+----------+ | id | name | +----+----------+ | 1 | Winston | | 7 | Jonathan | +----+----------+ Logins 表: +----+------------+ | id | login_date | +----+------------+ | 7 | 2020-05-30 | | 1 | 2020-05-30 | | 7 | 2020-05-31 | | 7 | 2020-06-01 | | 7 | 2020-06-02 | | 7 | 2020-06-02 | | 7 | 2020-06-03 | | 1 | 2020-06-07 | | 7 | 2020-06-10 | +----+------------+ 输出: +----+----------+ | id | name | +----+----------+ | 7 | Jonathan | +----+----------+ 解释: id = 1 的用户 Winston 仅仅在不同的 2 天内登录了 2 次, 所以, Winston 不是活跃用户. id = 7 的用户 Jonathon 在不同的 6 天内登录了 7 次, , 6 天中有 5 天是连续的, 所以, Jonathan 是活跃用户.
进阶问题:
如果活跃用户是那些至少连续 n
天登录账户的用户, 你能否写出通用的解决方案?
原站题解
mysql 解法, 执行用时: 1101 ms, 内存消耗: 0 B, 提交时间: 2023-10-16 17:13:33
select distinct a1.id, a1.name from `Accounts` as a1 inner join ( select id, @cnt:=if(@id=id and @pre_date=date_sub(login_date, interval 1 day), @cnt+1, 1) as cnt, @id:=id, @pre_date:=login_date from (select * from `Logins` group by id, login_date order by id, login_date) as a, (select @id:=null, @pre_date:=null, @cnt:=0) as b ) as b1 on a1.id = b1.id where b1.cnt >= 5 order by a1.id
mysql 解法, 执行用时: 933 ms, 内存消耗: 0 B, 提交时间: 2023-10-16 17:13:08
# 自连接 SELECT DISTINCT A.* FROM Accounts A JOIN logins L1 USING(id) JOIN Logins L2 ON L1.id=L2.id AND DATEDIFF(L2.login_date,L1.login_date) BETWEEN 0 AND 4 -- 对每个id相同的日期都只连接相差4天之内的日期。即对每个日期都检索一下是否有5个连续的日期。 -- 只要5天之内,日期有一个不连续,那么去重后每一组的天数必然少于5天。 GROUP BY A.id,A.name,L1.login_date HAVING COUNT(DISTINCT L2.login_date)=5
mysql 解法, 执行用时: 937 ms, 内存消耗: 0 B, 提交时间: 2023-10-16 17:12:51
# 窗口函数 select distinct id,name from ( select a.id,a.name,login_date,to_days(login_date) - row_number() over(partition by id order by login_date) as rn #对日期进行排序 from ( #获取去重的表格数据 select id, login_date from Logins group by id, login_date ) as t join Accounts as a where t.id = a.id ) as tt group by id,rn having count(*) >= 5