根据最小时间差减少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;
这假定 Timestamp 是 time 数据类型。这不会跨越日期边界工作,但相同的概念应该适用于日期时间类型。
我有一个带有事件条目的日志 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;
这假定 Timestamp 是 time 数据类型。这不会跨越日期边界工作,但相同的概念应该适用于日期时间类型。