Вы можете рассматривать это как проблему пробелов и островков. Оглянитесь назад и посмотрите, соответствует ли слово не , а затем накапливается и агрегируется:
with words as (
select t.*,
sum(case when prev_word is null or
word like prev_word || '%' or
prev_ts < ts - 60 -- say within a minute
then 1 else 0
end) as grp
from (select t.*,
lag(word) over (partition by userid order by ts) as prev_word,
lag(ts) over (partition by userid order by ts) as prev_ts
from t
) t
)
select w.*
from (select w.*,
row_number() over (partition by userid, grp order by ts desc) as seqnum
from words w
) w
where seqnum = 1;
На самом деле, есть более простой способ. Просто смотри вперед:
select w.*
from (select t.*,
lag(word) over (partition by userid order by ts) as next_word,
lead(ts) over (partition by userid order by ts) as next_ts
from t
) t
where next_ts is null or
next_ts > ts + 60 or
next_word not like word || '%';