根据最小时间差减少table条记录

Reduce table records based on minimum time difference

我有一个带有事件条目的日志 table (MS SQL SERVER)(事件是用户操作,如“用户登录”、“用户查看实体 A”等)。

某些事件(例如“用户查看实体 A”)可能会在短时间内发生多次。例如,如果用户在他的浏览器中前后移动,他可能会在一分钟内多次进入实体 A 的页面,并且将记录多个“用户查看”事件。

对于我的分析仪表板,我想计算用户查看实体 A 的次数,但我想对结果进行“去抖动”。我想将多个彼此接近的“用户视图”事件视为一个“用户视图”事件。具体来说,我只想考虑一个新的“用户视图”事件,前提是距离上一个事件超过 30 分钟。

所以有这样的 table(为清楚起见,最后一列是我的评论):

timestamp evt_type user_id entity_id *time diff from previous event
15:30 ENTITY_VIEW U1 E1 NULL (first view)
15:38 ENTITY_VIEW U1 E1 8mins
16:05 ENTITY_VIEW U1 E1 28mins
16:50 ENTITY_VIEW U1 E1 45mins (this counts as new view)
17:15 ENTITY_VIEW U1 E1 25mins
17:44 ENTITY_VIEW U1 E1 29mins
18:30 ENTITY_VIEW U1 E1 46mins (this counts as another view)

我想确定用户“查看”实体 3 次。

确定这一点的查询是什么?我尝试了 LEAD、LAG、PARTITION BY 和其他组合,但我似乎没有找到正确的方法,因为我不是 SQL 专家。

应该是一个简单的 LAG() 来获取以前的时间戳并检查差异。会说你的列 [timestamp] 是一个奇怪的数据类型,不同的日子呢?是否有单独的日期栏?

Return 记录距离上一个记录 >30 分钟

WITH cte_DeltaSinceLastView AS (
    SELECT *
        /*Grab previous record for each user_id/entity_id combo*/
        ,PrevTimestamp = LAG([timestamp]) OVER (PARTITION BY [user_id],[entity_id] ORDER BY [timestamp])
    FROM YourTable
    ) AS A(ID,[user_id],[entity_id],[timestamp])
)
SELECT *,MinutesSinceLastView = DATEDIFF(minute,PrevTimestamp,[Timestamp])
FROM cte_DeltaSinceLastView
WHERE DATEDIFF(minute,PrevTimestamp,[timestamp]) > 30 /*Over 30 minutes between last view*/
OR PrevTimestamp IS NULL /*First view will not have previous timestamp to compare against*/

您可以尝试的是相关子查询,它忽略前几行 30 分钟内的任何行,其余行应该是符合条件的行(即存在 30 分钟以上的间隔)。看看这对你有用吗?

select Sum(vc) as ViewedCount
from (
    select case when exists (
      select * from t t2 
        where t2.timestamp > t.timestamp 
          and t2.evt_type = t.evt_type 
          and t2.user_id = t.user_id 
          and t2.entity_id = t.entity_id
          and DateDiff(minute, t.timestamp,t2.timestamp) <30 
      ) then 0 else 1 end vc
    from t
)b;

这假定 Timestamptime 数据类型。这不会跨越日期边界工作,但相同的概念应该适用于日期时间类型。

Demo as Fiddle