Как ранжировать время события по заданному временному окну, используя SQL? - PullRequest
2 голосов
/ 27 января 2020

Я изо всех сил пытаюсь найти способ оценить события, используя SQL. Цель состоит в том, чтобы увеличивать ранг всякий раз, когда событие происходило более чем delta секунд (например, 1 секунда) от предыдущего наблюдения. Пока моя попытка показана ниже:

select a.event_time, a.user_name, a.object_name, a.rnk, case when a.ddif <= 1000 then 0 else 1 end as new_query,
            case when a.ddif <= 1000 then 0 else rnk end as new_rnk
from (
    select *, rank() OVER (PARTITION BY user_name ORDER BY event_time) AS rnk,
              date_diff('second',lag(event_time) OVER (PARTITION BY user_name ORDER BY event_time),event_time) as ddif
    from tmp
    ) a

Но она дает мне только следующие результаты, и я до сих пор не знаю, как добиться результатов в yellow (любой из них работает для меня отлично) ,

enter image description here

Буду признателен за любую помощь в этом.

Обратите внимание: я использую Presto DB , поэтому я ограничен этим механизмом запросов.

Ответы [ 3 ]

1 голос
/ 27 января 2020

Можно использовать lag() и окно sum():

select
    t.*,
    sum(case when event_time <= lag_event_time + interval '1' second then 0 else 1 end) rnk 
from (
    select 
        t.*, 
        lag(event_time) over(order by event_time partition by user_name) lag_event_time
    from mytable t
) t
1 голос
/ 27 января 2020

Спасибо за все полезные советы, которые указали мне направление к окончательному решению, а именно:

select a.*, sum (case when a.ddif <= 1 then 0 else 1 end) over (partition by user_name order by event_time) as acc_rnk
    from (
        select *, date_diff('second',lag(event_time) OVER (PARTITION BY user_name ORDER BY event_time),event_time) as ddif
        from tmp
        ) a
1 голос
/ 27 января 2020

Используйте lag() и совокупную сумму для определения групп. Затем присвойте номера строк:

select t.*,
       row_number() over (partition by user_name, grp order by event_time) as seqnum
from (select t.*,
             sum(case when prev_et > event_time - interval '1' second
                      then 0 else 1
                 end) over (partition by user_name order by event_time) as grp
      from (select t.*,
                   lag(event_time) over (partition by user_name order by event_time) as prev_et
            from tmp t
           ) t
     ) t;
...