首页 > 解决方案 > 查找唯一标识符重复的每个字段的最大序列号

问题描述

我有一个用户、ID 和活动时间戳的列表。数据按用户、ID、活动时间和基于所有这些维度分配的序列号排序。我需要根据序列号提取最早的时间戳,然后按每个用户和 ID 的序列号提取最新的时间戳。问题是当 ID 在当天晚些时候甚至第二天重复时,我的代码没有为每个 ID 拾取唯一的事件序列。

因此,如果用户 A 在 ID A123 上执行 5 个事件,然后在 ID A567 上移动以执行 6 个事件,然后返回 A123 以执行 4 个附加任务,我需要结果来反映 ID A123 上的第一个和最后一个活动,然后是 A567,然后又是 A123。

下面是我用来生成表格的当前代码:

SELECT 
user_id,
activity_date,
foc_id,
ROW_NUMBER() OVER ( PARTITION BY user_id, mno ORDER BY activity_date ) AS seq_num


FROM   cf.activity_history
MATCH_RECOGNIZE (
  PARTITION BY user_id
  ORDER     BY activity_date
  MEASURES
    MATCH_NUMBER() AS mno
  ALL ROWS PER MATCH
  PATTERN (same_foc_id * last_row  )
  DEFINE
    same_foc_id AS FIRST(foc_id) = NEXT(foc_id )
)

where 
user_id in ('UVAC3','UVAH161','UVEK29','UVRB152')
and (activity_date < (sysdate - 11)
and activity_date > (sysdate - 13))

order by
user_id,
activity_date,
foc_id

在此处输入图像描述

标签: sqloracledatetimegaps-and-islands

解决方案


这读起来就像一个间隙和孤岛问题:一个孤岛代表一系列“相邻”行,用户在其中执行相同的活动,并且您需要每个孤岛的开始和结束。

一种选择使用lead()lag()。假设foc_id识别活动:

select user_id, activity_date, foc_id
from (
    select a.*,
        lead(foc_id) over(partition by user_id order by activity_date) lead_foc_id,
        lag(foc_id) over(partition by user_id order by activity_date) lag_foc_id
    from cf.activity_history a
    where
        user_id in ('UVAC3', 'UVAH161', 'UVEK29', 'UVRB152')
        and activity_date < sysdate - 11
        and activity_date > sysdate - 13
) a
where 
    lead_foc_id is null 
    or lag_foc_id is null
    or foc_id <> lead_foc_id
    or foc_id <> lag_foc_id

推荐阅读