使用 SQL 获取 table 中每个用户的最近 n 天 activity

Using SQL to get recent n days activity of every user in the table

我有一个 table 游戏 activity 的用户看起来像这样

因此,为简单起见,只需考虑 account_id 和日期列。到目前为止,您可能已经了解每条记录代表一位玩家在特定日期玩某款游戏。我想提取的是最近 15 天 activity 每个用户从他上次玩的游戏开始倒数。例如,我们的数据范围是从 2020 年 4 月 4 日到 2020 年 9 月 24 日,假设一个用户在 2020 年 9 月 20 日玩了他的最后一场游戏并且从那以后就没有玩过任何游戏,所以对于那个用户我希望他玩 activity 的日期范围是 9 月 5 日到 20 日(从他上次玩游戏的前 15 天),我想为每个用户提取相同的数据。

我最初想这样实现......根据日期对 table 进行降序排序,并在 account_id 出现时将日期与该特定帐户匹配第一次(创建一个字典,其中键是 account_id,值是他最后一次玩的日期)这样我就可以从值中减去 15 天并过滤每个 account_id 的数据,但是我的同事worker 对此并不满意,并希望一次完成所有这些(使用 SQL 查询)。有人可以指导我如何做到这一点。提前致谢:)

如果我理解正确的话,您基本上是在寻找 MAX(Date) Grouped BY User 作为您的起点(实际上是终点)。

将它放在子查询或 CTE 中是最简单的。

然后您可以简单地再次查询您的 table,使用用户的最后日期作为您的结束日期,并计算该日期 - 15 天作为您的起点。

这将检索给定时间段内用户的所有条目。

示例:

WITH BASE AS( 
SELECT 
MAX(Date) AS LastDate, 
UserID 
FROM GameActivity 
GROUP BY UserID
) 
SELECT 
ga.UserID, 
ga.Date
FROM GameActivity GA 
JOIN BASE B ON b.UserID = ga.UserID 
WHERE ga.Date >= DATE_SUB(b.LastDate, INTERVAL 15 DAY) 
  AND ga.Date <= b.LastDate  

编辑:

为了得到过去 15 天而不考虑实际日期,我个人会使用 Window 函数来倒数 我将其分成 2 个 CTE 以突出逻辑

WITH DistinctDates AS (
SELECT DISTINCT 
user_id, 
active_date
  
FROM userdata
), 

DAYCount AS ( 
SELECT 
user_id, 
active_date, 
COUNT(active_date) OVER (PARTITION BY user_id ORDER BY active_date DESC) AS ActiveDays

FROM DistinctDates 
) 

SELECT 
dc.user_id, 
ud.active_date,
dc.ActiveDays 

FROM DayCount DC
JOIN userdata UD ON ud.user_id = dc.user_id AND ud.active_date = dc.active_date

WHERE ActiveDays BETWEEN 1 AND 15 

ORDER BY dc.user_id, dc.ActiveDays ; 

我在 MS SQL 服务器上尝试过,但 MySQL 应该可以正常工作

如果你是 运行 MySQL 8.0,你可以使用 window 函数来做到这一点:

select *
from (
    select t.*, max(date) over(partition by account_id) max_date
    from mytable t
) t
where date >= max_date - interval 15 day

在早期版本中,替代方法是相关子查询:

select *
from mytable t
where date >= (select max(t1.date) from mytable t1 where t1.account_id = t.account_id) - interval 15 day

或使用连接:

select *
from mytable t
inner join (select account_id, max(date) max_date from mytable group by account_id) m
    on t.date >= m.max_date - interval 15 day